From: Mark Thom Date: Sun, 21 Feb 2021 23:28:30 +0000 (-0700) Subject: wrap stream instances in one Rc>, use Ref/RefMut to access stream options X-Git-Tag: v0.9.0~150^2~24 X-Git-Url: https://git.sagredo.dev/?a=commitdiff_plain;h=a323a4dd8e0c18ea6be8f83334575f0acb5685e9;p=scryer-prolog.git wrap stream instances in one Rc>, use Ref/RefMut to access stream options --- diff --git a/src/heap_print.rs b/src/heap_print.rs index aadd2e0f..a7250c2f 100644 --- a/src/heap_print.rs +++ b/src/heap_print.rs @@ -1363,7 +1363,7 @@ impl<'a, Outputter: HCValueOutputter> HCPrinter<'a, Outputter> { } fn print_stream(&mut self, iter: &mut HCPreOrderIterator, stream: &Stream, max_depth: usize) { - if let Some(alias) = &stream.options.alias { + if let Some(alias) = &stream.options().alias { self.print_atom(alias); } else { if self.format_struct(iter, max_depth, 1, clause_name!("$stream")) { diff --git a/src/machine/machine_state.rs b/src/machine/machine_state.rs index 96964b1e..ab372549 100644 --- a/src/machine/machine_state.rs +++ b/src/machine/machine_state.rs @@ -308,7 +308,7 @@ impl MachineState { )?; if stream.past_end_of_stream() { - if EOFAction::Reset != stream.options.eof_action { + if EOFAction::Reset != stream.options().eof_action { return return_from_clause!(self.last_call, self); } else if self.fail { return Ok(()); @@ -402,7 +402,7 @@ impl MachineState { 3, )?; - if orig_stream.options.eof_action == EOFAction::Reset { + if orig_stream.options().eof_action == EOFAction::Reset { if self.fail == false { continue; } diff --git a/src/machine/mod.rs b/src/machine/mod.rs index a919f3c4..b9247176 100644 --- a/src/machine/mod.rs +++ b/src/machine/mod.rs @@ -387,7 +387,7 @@ impl Machine { } pub fn configure_streams(&mut self) { - self.user_input.options.alias = Some(clause_name!("user_input")); + self.user_input.options_mut().alias = Some(clause_name!("user_input")); self.indices .stream_aliases @@ -395,7 +395,7 @@ impl Machine { self.indices.streams.insert(self.user_input.clone()); - self.user_output.options.alias = Some(clause_name!("user_output")); + self.user_output.options_mut().alias = Some(clause_name!("user_output")); self.indices .stream_aliases diff --git a/src/machine/streams.rs b/src/machine/streams.rs index 21ffbbda..f4c182ce 100644 --- a/src/machine/streams.rs +++ b/src/machine/streams.rs @@ -197,13 +197,25 @@ impl fmt::Debug for StreamInstance { } } +#[derive(Debug)] +struct InnerStream { + options: StreamOptions, + stream_inst: StreamInstance, + past_end_of_stream: bool, +} + #[derive(Debug, Clone)] -struct WrappedStreamInstance(Rc>); +struct WrappedStreamInstance(Rc>); impl WrappedStreamInstance { #[inline] - fn new(stream_inst: StreamInstance) -> Self { - WrappedStreamInstance(Rc::new(RefCell::new((false, stream_inst)))) + fn new(stream_inst: StreamInstance, past_end_of_stream: bool) -> Self { + WrappedStreamInstance(Rc::new(RefCell::new( + InnerStream { + options: StreamOptions::default(), + stream_inst, + past_end_of_stream } + ))) } } @@ -293,7 +305,6 @@ impl Default for StreamOptions { #[derive(Debug, Clone, Hash)] pub struct Stream { - pub options: StreamOptions, stream_inst: WrappedStreamInstance, } @@ -352,9 +363,25 @@ impl Stream { ptr as *const u8 } + #[inline] + pub(crate) fn options(&self) -> std::cell::Ref<'_, StreamOptions> { + std::cell::Ref::map( + self.stream_inst.0.borrow(), + |inner_stream| &inner_stream.options, + ) + } + + #[inline] + pub(crate) fn options_mut(&mut self) -> std::cell::RefMut<'_, StreamOptions> { + std::cell::RefMut::map( + self.stream_inst.0.borrow_mut(), + |inner_stream| &mut inner_stream.options, + ) + } + #[inline] pub(crate) fn position(&mut self) -> Option { - match self.stream_inst.0.borrow_mut().1 { + match self.stream_inst.0.borrow_mut().stream_inst { StreamInstance::InputFile(_, ref mut file) => file.seek(SeekFrom::Current(0)).ok(), _ => None, } @@ -363,7 +390,9 @@ impl Stream { #[inline] pub(crate) fn set_position(&mut self, position: u64) { match self.stream_inst.0.borrow_mut().deref_mut() { - (past_end_of_stream, StreamInstance::InputFile(_, ref mut file)) => { + InnerStream { past_end_of_stream, + stream_inst: StreamInstance::InputFile(_, ref mut file), + .. } => { file.seek(SeekFrom::Start(position)).unwrap(); if let Ok(metadata) = file.metadata() { @@ -376,7 +405,7 @@ impl Stream { #[inline] pub(crate) fn past_end_of_stream(&self) -> bool { - self.stream_inst.0.borrow_mut().0 + self.stream_inst.0.borrow_mut().past_end_of_stream } #[inline] @@ -386,7 +415,7 @@ impl Stream { #[inline] pub(crate) fn set_past_end_of_stream(&mut self) { - self.stream_inst.0.borrow_mut().0 = true; + self.stream_inst.0.borrow_mut().past_end_of_stream = true; } #[inline] @@ -396,7 +425,9 @@ impl Stream { } match self.stream_inst.0.borrow_mut().deref_mut() { - (past_end_of_stream, StreamInstance::InputFile(_, ref mut file)) => { + InnerStream { past_end_of_stream, + stream_inst: StreamInstance::InputFile(_, ref mut file), + .. } => { match file.metadata() { Ok(metadata) => { if let Ok(position) = file.seek(SeekFrom::Current(0)) { @@ -404,17 +435,17 @@ impl Stream { Ordering::Equal => AtEndOfStream::At, Ordering::Less => AtEndOfStream::Not, Ordering::Greater => { - *past_end_of_stream = true; //self.set_past_end_of_stream(); + *past_end_of_stream = true; AtEndOfStream::Past } }; } else { - *past_end_of_stream = true; //self.set_past_end_of_stream(); + *past_end_of_stream = true; AtEndOfStream::Past } } _ => { - *past_end_of_stream = true; //self.set_past_end_of_stream(); + *past_end_of_stream = true; AtEndOfStream::Past } } @@ -425,7 +456,7 @@ impl Stream { #[inline] pub(crate) fn file_name(&self) -> Option { - match self.stream_inst.0.borrow().1 { + match self.stream_inst.0.borrow().stream_inst { StreamInstance::InputFile(ref name, _) => Some(name.clone()), StreamInstance::OutputFile(ref name, ..) => Some(name.clone()), StreamInstance::TcpStream(ref name, _) => Some(name.clone()), @@ -435,12 +466,12 @@ impl Stream { #[inline] pub(crate) fn mode(&self) -> &'static str { - match self.stream_inst.0.borrow().1 { - StreamInstance::Bytes(_) - | StreamInstance::PausedPrologStream(..) - | StreamInstance::ReadlineStream(_) - | StreamInstance::StaticStr(_) - | StreamInstance::InputFile(..) => "read", + match self.stream_inst.0.borrow().stream_inst { + StreamInstance::Bytes(_) | + StreamInstance::PausedPrologStream(..) | + StreamInstance::ReadlineStream(_) | + StreamInstance::StaticStr(_) | + StreamInstance::InputFile(..) => "read", StreamInstance::TcpStream(..) | StreamInstance::TlsStream(..) => "read_append", StreamInstance::OutputFile(_, _, true) => "append", StreamInstance::Stdout | StreamInstance::OutputFile(_, _, false) => "write", @@ -451,8 +482,7 @@ impl Stream { #[inline] fn from_inst(stream_inst: StreamInstance) -> Self { Stream { - options: StreamOptions::default(), - stream_inst: WrappedStreamInstance::new(stream_inst), + stream_inst: WrappedStreamInstance::new(stream_inst, false), } } @@ -486,7 +516,7 @@ impl Stream { #[inline] pub(crate) fn is_stdout(&self) -> bool { - match self.stream_inst.0.borrow().1 { + match self.stream_inst.0.borrow().stream_inst { StreamInstance::Stdout => true, _ => false, } @@ -494,7 +524,7 @@ impl Stream { #[inline] pub(crate) fn is_stdin(&self) -> bool { - match self.stream_inst.0.borrow().1 { + match self.stream_inst.0.borrow().stream_inst { StreamInstance::ReadlineStream(_) => true, _ => false, } @@ -502,12 +532,12 @@ impl Stream { #[inline] pub(crate) fn close(&mut self) { - self.stream_inst.0.borrow_mut().1 = StreamInstance::Null; + self.stream_inst.0.borrow_mut().stream_inst = StreamInstance::Null; } #[inline] pub(crate) fn is_null_stream(&self) -> bool { - if let StreamInstance::Null = self.stream_inst.0.borrow().1 { + if let StreamInstance::Null = self.stream_inst.0.borrow().stream_inst { true } else { false @@ -516,32 +546,32 @@ impl Stream { #[inline] pub(crate) fn is_input_stream(&self) -> bool { - match self.stream_inst.0.borrow().1 { - StreamInstance::TcpStream(..) - | StreamInstance::TlsStream(..) - | StreamInstance::Bytes(_) - | StreamInstance::PausedPrologStream(..) - | StreamInstance::ReadlineStream(_) - | StreamInstance::StaticStr(_) - | StreamInstance::InputFile(..) => true, + match self.stream_inst.0.borrow().stream_inst { + StreamInstance::TcpStream(..) | + StreamInstance::TlsStream(..) | + StreamInstance::Bytes(_) | + StreamInstance::PausedPrologStream(..) | + StreamInstance::ReadlineStream(_) | + StreamInstance::StaticStr(_) | + StreamInstance::InputFile(..) => true, _ => false, } } #[inline] pub(crate) fn is_output_stream(&self) -> bool { - match self.stream_inst.0.borrow().1 { - StreamInstance::Stdout - | StreamInstance::TcpStream(..) - | StreamInstance::TlsStream(..) - | StreamInstance::Bytes(_) - | StreamInstance::OutputFile(..) => true, + match self.stream_inst.0.borrow().stream_inst { + StreamInstance::Stdout | + StreamInstance::TcpStream(..) | + StreamInstance::TlsStream(..) | + StreamInstance::Bytes(_) | + StreamInstance::OutputFile(..) => true, _ => false, } } fn unpause_stream(&mut self) { - let stream_inst = match self.stream_inst.0.borrow_mut().1 { + let stream_inst = match self.stream_inst.0.borrow_mut().stream_inst { StreamInstance::PausedPrologStream(ref put_back, ref mut stream_inst) if put_back.is_empty() => { @@ -552,16 +582,16 @@ impl Stream { } }; - self.stream_inst.0.borrow_mut().1 = stream_inst; + self.stream_inst.0.borrow_mut().stream_inst = stream_inst; } // returns true on success. #[inline] pub(super) fn reset(&mut self) -> bool { - self.stream_inst.0.borrow_mut().0 = false; + self.stream_inst.0.borrow_mut().past_end_of_stream = false; loop { - match self.stream_inst.0.borrow_mut().1 { + match self.stream_inst.0.borrow_mut().stream_inst { StreamInstance::Bytes(ref mut cursor) => { cursor.set_position(0); return true; @@ -587,7 +617,7 @@ impl Stream { #[inline] pub(crate) fn peek_byte(&mut self) -> std::io::Result { - match self.stream_inst.0.borrow_mut().1 { + match self.stream_inst.0.borrow_mut().stream_inst { StreamInstance::Bytes(ref mut cursor) => { let mut b = [0u8; 1]; let pos = cursor.position(); @@ -631,7 +661,7 @@ impl Stream { pub(crate) fn peek_char(&mut self) -> std::io::Result { use unicode_reader::CodePoints; - match self.stream_inst.0.borrow_mut().1 { + match self.stream_inst.0.borrow_mut().stream_inst { StreamInstance::InputFile(_, ref mut file) => { let c = { let mut iter = CodePoints::from(&*file); @@ -679,7 +709,7 @@ impl Stream { #[inline] pub(crate) fn pause_stream(&mut self, buf: Vec>) -> io::Result<()> { - match self.stream_inst.0.borrow_mut().1 { + match self.stream_inst.0.borrow_mut().stream_inst { StreamInstance::PausedPrologStream(ref mut inner_buf, _) => { inner_buf.extend(parser_top_to_bytes(buf)?.into_iter()); return Ok(()); @@ -688,10 +718,12 @@ impl Stream { } if !buf.is_empty() { - let stream_inst = - mem::replace(&mut self.stream_inst.0.borrow_mut().1, StreamInstance::Null); + let stream_inst = mem::replace( + &mut self.stream_inst.0.borrow_mut().stream_inst, + StreamInstance::Null, + ); - self.stream_inst.0.borrow_mut().1 = StreamInstance::PausedPrologStream( + self.stream_inst.0.borrow_mut().stream_inst = StreamInstance::PausedPrologStream( parser_top_to_bytes(buf)?, Box::new(stream_inst), ); @@ -710,13 +742,15 @@ impl MachineState { caller: ClauseName, arity: usize, ) -> CallResult { - match stream.options.eof_action { + let eof_action = stream.options().eof_action; + + match eof_action { EOFAction::Error => { stream.set_past_end_of_stream(); return Err(self.open_past_eos_error(stream.clone(), caller, arity)); } EOFAction::EOFCode => { - let end_of_stream = if stream.options.stream_type == StreamType::Binary { + let end_of_stream = if stream.options().stream_type == StreamType::Binary { Addr::Fixnum(-1) } else { self.heap @@ -979,7 +1013,7 @@ impl MachineState { Some("stream") // 8.14.2.3 g) } else if input.is_none() && !stream.is_output_stream() { Some("stream") // 8.14.2.3 g) - } else if stream.options.stream_type != expected_type { + } else if stream.options().stream_type != expected_type { Some(expected_type.other().as_str()) // 8.14.2.3 h) } else { None @@ -1014,7 +1048,7 @@ impl MachineState { impl Read for Stream { #[inline] fn read(&mut self, buf: &mut [u8]) -> std::io::Result { - let bytes_read = self.stream_inst.0.borrow_mut().1.read(buf)?; + let bytes_read = self.stream_inst.0.borrow_mut().stream_inst.read(buf)?; self.unpause_stream(); Ok(bytes_read) } @@ -1022,17 +1056,17 @@ impl Read for Stream { impl Write for Stream { fn write(&mut self, buf: &[u8]) -> std::io::Result { - match self.stream_inst.0.borrow_mut().1 { + match self.stream_inst.0.borrow_mut().stream_inst { StreamInstance::OutputFile(_, ref mut file, _) => file.write(buf), StreamInstance::TcpStream(_, ref mut tcp_stream) => tcp_stream.write(buf), StreamInstance::TlsStream(_, ref mut tls_stream) => tls_stream.write(buf), StreamInstance::Bytes(ref mut cursor) => cursor.write(buf), StreamInstance::Stdout => stdout().write(buf), - StreamInstance::PausedPrologStream(..) - | StreamInstance::StaticStr(_) - | StreamInstance::ReadlineStream(_) - | StreamInstance::InputFile(..) - | StreamInstance::Null => Err(std::io::Error::new( + StreamInstance::PausedPrologStream(..) | + StreamInstance::StaticStr(_) | + StreamInstance::ReadlineStream(_) | + StreamInstance::InputFile(..) | + StreamInstance::Null => Err(std::io::Error::new( ErrorKind::PermissionDenied, StreamError::WriteToInputStream, )), @@ -1040,17 +1074,17 @@ impl Write for Stream { } fn flush(&mut self) -> std::io::Result<()> { - match self.stream_inst.0.borrow_mut().1 { + match self.stream_inst.0.borrow_mut().stream_inst { StreamInstance::OutputFile(_, ref mut file, _) => file.flush(), StreamInstance::TcpStream(_, ref mut tcp_stream) => tcp_stream.flush(), StreamInstance::TlsStream(_, ref mut tls_stream) => tls_stream.flush(), StreamInstance::Bytes(ref mut cursor) => cursor.flush(), StreamInstance::Stdout => stdout().flush(), - StreamInstance::PausedPrologStream(..) - | StreamInstance::StaticStr(_) - | StreamInstance::ReadlineStream(_) - | StreamInstance::InputFile(..) - | StreamInstance::Null => Err(std::io::Error::new( + StreamInstance::PausedPrologStream(..) | + StreamInstance::StaticStr(_) | + StreamInstance::ReadlineStream(_) | + StreamInstance::InputFile(..) | + StreamInstance::Null => Err(std::io::Error::new( ErrorKind::PermissionDenied, StreamError::FlushToInputStream, )), diff --git a/src/machine/system_calls.rs b/src/machine/system_calls.rs index 8251c3fe..12039b02 100644 --- a/src/machine/system_calls.rs +++ b/src/machine/system_calls.rs @@ -467,7 +467,7 @@ impl MachineState { } else { self.p.local() + 1 }; - + Ok(self.p = CodePtr::REPL(repl_code_ptr, p)) } @@ -1319,7 +1319,7 @@ impl MachineState { )?; if stream.past_end_of_stream() { - if EOFAction::Reset != stream.options.eof_action { + if EOFAction::Reset != stream.options().eof_action { return return_from_clause!(self.last_call, self); } else if self.fail { return Ok(()); @@ -1395,7 +1395,7 @@ impl MachineState { 2, )?; - if EOFAction::Reset != stream.options.eof_action { + if EOFAction::Reset != stream.options().eof_action { return return_from_clause!(self.last_call, self); } else if self.fail { return Ok(()); @@ -1417,7 +1417,7 @@ impl MachineState { )?; if stream.past_end_of_stream() { - if EOFAction::Reset != stream.options.eof_action { + if EOFAction::Reset != stream.options().eof_action { return return_from_clause!(self.last_call, self); } else if self.fail { return Ok(()); @@ -1491,7 +1491,7 @@ impl MachineState { 2, )?; - if EOFAction::Reset != stream.options.eof_action { + if EOFAction::Reset != stream.options().eof_action { return return_from_clause!(self.last_call, self); } else if self.fail { return Ok(()); @@ -1520,7 +1520,7 @@ impl MachineState { )?; if stream.past_end_of_stream() { - if EOFAction::Reset != stream.options.eof_action { + if EOFAction::Reset != stream.options().eof_action { return return_from_clause!(self.last_call, self); } else if self.fail { return Ok(()); @@ -1610,7 +1610,7 @@ impl MachineState { 2, )?; - if EOFAction::Reset != stream.options.eof_action { + if EOFAction::Reset != stream.options().eof_action { return return_from_clause!(self.last_call, self); } else if self.fail { return Ok(()); @@ -2027,7 +2027,7 @@ impl MachineState { let mut bytes = Vec::new(); let string = self.heap_pstr_iter(self[temp_v!(2)]).to_string(); - if stream.options.stream_type == StreamType::Binary { + if stream.options().stream_type == StreamType::Binary { for c in string.chars() { if c as u32 > 255 { let stub = MachineError::functor_stub(clause_name!("$put_chars"), 2); @@ -2172,7 +2172,7 @@ impl MachineState { if stream.past_end_of_stream() { self.eof_action(self[temp_v!(2)], &mut stream, clause_name!("get_byte"), 2)?; - if EOFAction::Reset != stream.options.eof_action { + if EOFAction::Reset != stream.options().eof_action { return return_from_clause!(self.last_call, self); } else if self.fail { return Ok(()); @@ -2253,7 +2253,7 @@ impl MachineState { )?; if stream.past_end_of_stream() { - if EOFAction::Reset != stream.options.eof_action { + if EOFAction::Reset != stream.options().eof_action { return return_from_clause!(self.last_call, self); } else if self.fail { return Ok(()); @@ -2327,7 +2327,7 @@ impl MachineState { 2, )?; - if EOFAction::Reset != stream.options.eof_action { + if EOFAction::Reset != stream.options().eof_action { return return_from_clause!(self.last_call, self); } else if self.fail { return Ok(()); @@ -2363,7 +2363,7 @@ impl MachineState { let mut string = String::new(); - if stream.options.stream_type == StreamType::Binary { + if stream.options().stream_type == StreamType::Binary { let mut buf = vec![]; let mut chunk = stream.take(num as u64); chunk.read_to_end(&mut buf).ok(); @@ -2402,7 +2402,7 @@ impl MachineState { )?; if stream.past_end_of_stream() { - if EOFAction::Reset != stream.options.eof_action { + if EOFAction::Reset != stream.options().eof_action { return return_from_clause!(self.last_call, self); } else if self.fail { return Ok(()); @@ -2490,7 +2490,7 @@ impl MachineState { 2, )?; - if EOFAction::Reset != stream.options.eof_action { + if EOFAction::Reset != stream.options().eof_action { return return_from_clause!(self.last_call, self); } else if self.fail { return Ok(()); @@ -2664,8 +2664,8 @@ impl MachineState { if !stream.is_stdin() && !stream.is_stdout() { stream.close(); - if let Some(alias) = stream.options.alias { - indices.stream_aliases.remove(&alias); + if let Some(ref alias) = stream.options().alias { + indices.stream_aliases.remove(alias); } } } @@ -3153,11 +3153,11 @@ impl MachineState { _ => self.stream_from_file_spec(clause_name!(""), indices, &options)?, }; - stream.options = options; + *stream.options_mut() = options; indices.streams.insert(stream.clone()); - if let Some(ref alias) = &stream.options.alias { + if let Some(ref alias) = &stream.options().alias { indices.stream_aliases.insert(alias.clone(), stream.clone()); } @@ -4261,9 +4261,9 @@ impl MachineState { } }; - stream.options = options; + *stream.options_mut() = options; - if let Some(ref alias) = &stream.options.alias { + if let Some(ref alias) = &stream.options().alias { indices.stream_aliases.insert(alias.clone(), stream.clone()); } @@ -4398,9 +4398,9 @@ impl MachineState { let mut tcp_stream = Stream::from_tcp_stream(client.clone(), tcp_stream); - tcp_stream.options = options; + *tcp_stream.options_mut() = options; - if let Some(ref alias) = &tcp_stream.options.alias { + if let Some(ref alias) = &tcp_stream.options().alias { indices .stream_aliases .insert(alias.clone(), tcp_stream.clone()); @@ -4467,7 +4467,7 @@ impl MachineState { let mut stream = self.get_stream_or_alias(self[temp_v!(1)], indices, "set_stream_position", 2)?; - if !stream.options.reposition { + if !stream.options().reposition { let stub = MachineError::functor_stub(clause_name!("set_stream_position"), 2); let err = MachineError::permission_error( @@ -4526,7 +4526,7 @@ impl MachineState { None, ), "alias" => { - if let Some(alias) = &stream.options.alias { + if let Some(alias) = &stream.options().alias { HeapCellValue::Atom(alias.clone(), None) } else { self.fail = true; @@ -4547,11 +4547,11 @@ impl MachineState { HeapCellValue::Atom(clause_name!(end_of_stream_pos.as_str()), None) } "eof_action" => HeapCellValue::Atom( - clause_name!(stream.options.eof_action.as_str()), + clause_name!(stream.options().eof_action.as_str()), None, ), "reposition" => HeapCellValue::Atom( - clause_name!(if stream.options.reposition { + clause_name!(if stream.options().reposition { "true" } else { "false" @@ -4559,7 +4559,7 @@ impl MachineState { None, ), "type" => HeapCellValue::Atom( - clause_name!(stream.options.stream_type.as_property_str()), + clause_name!(stream.options().stream_type.as_property_str()), None, ), _ => { @@ -4815,7 +4815,7 @@ impl MachineState { let opt_err = if !stream.is_output_stream() { Some("stream") // 8.14.2.3 g) - } else if stream.options.stream_type == StreamType::Binary { + } else if stream.options().stream_type == StreamType::Binary { Some("binary_stream") // 8.14.2.3 h) } else { None