use std::cell::RefCell;
use std::hash::{DefaultHasher, Hash, Hasher};
use std::io::{Read, Seek};
use std::rc::{Rc, Weak as RcWeak};
use std::sync::{Arc, Mutex as StdMutex, RwLock as StdRwLock, Weak as ArcWeak};
use std::any::{Any, TypeId};
use parking_lot::{Mutex, RwLock};
use crate::{
cache::{BasicCache, ParsingCache},
result::{Error, ParseResult},
};
pub trait Parsable: Read + Seek {}
impl<T> Parsable for T where T: Read + Seek {}
pub struct Source<S> {
source: S,
stack: Vec<u64>,
index: u64,
}
impl<S> Source<S>
where
S: Parsable,
{
pub fn new(mut source: S) -> Source<S> {
let index = source.stream_position().unwrap_or(0);
Source {
source,
stack: Vec::with_capacity(20),
index,
}
}
pub fn push(&mut self) {
self.stack.push(self.index);
}
pub fn pop(&mut self) {
self.index = self.stack.pop().unwrap_or(0);
}
pub fn commit(&mut self) {
self.stack.pop();
}
pub fn peek1(&mut self) -> Result<u8, Error> {
let mut buf = [0; 1];
self.source.seek(std::io::SeekFrom::Start(self.index))?;
if let Err(err) = self.source.read_exact(&mut buf) {
if err.kind() == std::io::ErrorKind::UnexpectedEof {
return Err(Error::NoMatch);
}
return Err(Error::from(err));
}
Ok(buf[0])
}
pub fn peek(&mut self, bytes: usize) -> Result<Vec<u8>, Error> {
let mut buf = vec![0; bytes];
self.source.seek(std::io::SeekFrom::Start(self.index))?;
if let Err(err) = self.source.read_exact(&mut buf) {
if err.kind() == std::io::ErrorKind::UnexpectedEof {
return Err(Error::NoMatch);
}
return Err(Error::from(err));
}
Ok(buf)
}
pub fn advance(&mut self, bytes: usize) {
self.index += bytes as u64;
}
pub fn read(&mut self, bytes: usize) -> Result<Vec<u8>, Error> {
let ret = self.peek(bytes)?;
self.advance(bytes);
Ok(ret)
}
}
pub trait Parser<Ctx = ()>
where
Self: Any,
{
type Output: Any + Clone;
fn read<S>(
&self,
source: &mut Source<S>,
cache: &mut impl ParsingCache,
context: &mut Ctx,
) -> ParseResult<Self::Output>
where
S: Parsable;
fn id(&self) -> u64 {
let mut hasher = DefaultHasher::new();
TypeId::of::<Self>().hash(&mut hasher);
hasher.finish()
}
fn parse<S>(
&self,
source: &mut Source<S>,
cache: &mut impl ParsingCache,
context: &mut Ctx,
) -> ParseResult<Self::Output>
where
S: Parsable,
{
let parser_id = self.id();
let before = source.index;
if let Some((cached_result, after)) = cache.lookup::<Self::Output>(parser_id, before) {
source.index = after;
return Ok(cached_result);
}
source.push();
match self.read(source, cache, context) {
Ok(val) => {
source.commit();
cache.record::<Self::Output>(parser_id, before, val.clone(), source.index);
Ok(val)
}
Err(err) => match err {
Error::NoMatch => {
source.pop();
Err(err)
}
_ => Err(err),
},
}
}
}
pub fn parse<R, S>(parser: R, source: &mut Source<S>) -> Result<R::Output, Error>
where
R: Parser,
S: Parsable,
{
let mut cache = BasicCache::new();
let mut context = ();
parser.parse(source, &mut cache, &mut context)
}
pub fn parse_with_cache<R, S>(
parser: R,
source: &mut Source<S>,
cache: &mut impl ParsingCache,
) -> Result<R::Output, Error>
where
R: Parser,
S: Parsable,
{
let mut context = ();
parser.parse(source, cache, &mut context)
}
pub fn parse_with_context<R, S, Ctx>(
parser: R,
source: &mut Source<S>,
context: &mut Ctx,
) -> Result<R::Output, Error>
where
R: Parser<Ctx>,
S: Parsable,
{
let mut cache = BasicCache::new();
parser.parse(source, &mut cache, context)
}
pub fn parse_with_cache_and_context<R, S, Ctx>(
parser: R,
source: &mut Source<S>,
cache: &mut impl ParsingCache,
context: &mut Ctx,
) -> Result<R::Output, Error>
where
R: Parser<Ctx>,
S: Parsable,
{
parser.parse(source, cache, context)
}
impl<Ctx> Parser<Ctx> for () {
type Output = ();
fn read<S>(
&self,
_source: &mut Source<S>,
_cache: &mut impl ParsingCache,
_context: &mut Ctx,
) -> ParseResult<Self::Output>
where
S: Parsable,
{
Ok(())
}
}
impl<T, Ctx> Parser<Ctx> for Box<T>
where
T: Parser<Ctx>,
{
type Output = T::Output;
fn id(&self) -> u64 {
self.as_ref().id()
}
fn read<S>(
&self,
source: &mut Source<S>,
cache: &mut impl ParsingCache,
context: &mut Ctx,
) -> ParseResult<Self::Output>
where
S: Parsable,
{
self.as_ref().read(source, cache, context)
}
}
impl<T, Ctx> Parser<Ctx> for Arc<T>
where
T: Parser<Ctx>,
{
type Output = T::Output;
fn id(&self) -> u64 {
self.as_ref().id()
}
fn read<S>(
&self,
source: &mut Source<S>,
cache: &mut impl ParsingCache,
context: &mut Ctx,
) -> ParseResult<Self::Output>
where
S: Parsable,
{
self.as_ref().read(source, cache, context)
}
}
impl<T, Ctx> Parser<Ctx> for Rc<T>
where
T: Parser<Ctx>,
{
type Output = T::Output;
fn id(&self) -> u64 {
self.as_ref().id()
}
fn read<S>(
&self,
source: &mut Source<S>,
cache: &mut impl ParsingCache,
context: &mut Ctx,
) -> ParseResult<Self::Output>
where
S: Parsable,
{
self.as_ref().read(source, cache, context)
}
}
impl<T, Ctx> Parser<Ctx> for Mutex<T>
where
T: Parser<Ctx>,
{
type Output = T::Output;
fn id(&self) -> u64 {
self.lock().id()
}
fn read<S>(
&self,
source: &mut Source<S>,
cache: &mut impl ParsingCache,
context: &mut Ctx,
) -> ParseResult<Self::Output>
where
S: Parsable,
{
self.lock().read(source, cache, context)
}
}
impl<T, Ctx> Parser<Ctx> for RwLock<T>
where
T: Parser<Ctx>,
{
type Output = T::Output;
fn id(&self) -> u64 {
self.read().id()
}
fn read<S>(
&self,
source: &mut Source<S>,
cache: &mut impl ParsingCache,
context: &mut Ctx,
) -> ParseResult<Self::Output>
where
S: Parsable,
{
self.read().read(source, cache, context)
}
}
impl<T, Ctx> Parser<Ctx> for RefCell<T>
where
T: Parser<Ctx>,
{
type Output = T::Output;
fn id(&self) -> u64 {
self.borrow().id()
}
fn read<S>(
&self,
source: &mut Source<S>,
cache: &mut impl ParsingCache,
context: &mut Ctx,
) -> ParseResult<Self::Output>
where
S: Parsable,
{
self.borrow().read(source, cache, context)
}
}
impl<T, Ctx> Parser<Ctx> for StdMutex<T>
where
T: Parser<Ctx>,
{
type Output = T::Output;
fn id(&self) -> u64 {
self.lock().expect("Mutex poisoned").id()
}
fn read<S>(
&self,
source: &mut Source<S>,
cache: &mut impl ParsingCache,
context: &mut Ctx,
) -> ParseResult<Self::Output>
where
S: Parsable,
{
self.lock()
.expect("Mutex poisoned")
.read(source, cache, context)
}
}
impl<T, Ctx> Parser<Ctx> for StdRwLock<T>
where
T: Parser<Ctx>,
{
type Output = T::Output;
fn id(&self) -> u64 {
self.read().expect("RwLock poisoned").id()
}
fn read<S>(
&self,
source: &mut Source<S>,
cache: &mut impl ParsingCache,
context: &mut Ctx,
) -> ParseResult<Self::Output>
where
S: Parsable,
{
self.read()
.expect("RwLock poisoned")
.read(source, cache, context)
}
}
impl<T, Ctx> Parser<Ctx> for ArcWeak<T>
where
T: Parser<Ctx>,
{
type Output = T::Output;
fn id(&self) -> u64 {
if let Some(strong) = self.upgrade() {
strong.as_ref().id()
} else {
let mut hasher = DefaultHasher::new();
TypeId::of::<ArcWeak<T>>().hash(&mut hasher);
hasher.finish()
}
}
fn read<S>(
&self,
source: &mut Source<S>,
cache: &mut impl ParsingCache,
context: &mut Ctx,
) -> ParseResult<Self::Output>
where
S: Parsable,
{
if let Some(strong) = self.upgrade() {
strong.as_ref().read(source, cache, context)
} else {
Err(Error::NoMatch)
}
}
}
impl<T, Ctx> Parser<Ctx> for RcWeak<T>
where
T: Parser<Ctx>,
{
type Output = T::Output;
fn id(&self) -> u64 {
if let Some(strong) = self.upgrade() {
strong.as_ref().id()
} else {
let mut hasher = DefaultHasher::new();
TypeId::of::<RcWeak<T>>().hash(&mut hasher);
hasher.finish()
}
}
fn read<S>(
&self,
source: &mut Source<S>,
cache: &mut impl ParsingCache,
context: &mut Ctx,
) -> ParseResult<Self::Output>
where
S: Parsable,
{
if let Some(strong) = self.upgrade() {
strong.as_ref().read(source, cache, context)
} else {
Err(Error::NoMatch)
}
}
}
#[cfg(test)]
mod tests {
use super::*;
use crate::cache::{BasicCache, NoCache};
use std::io::Cursor;
#[test]
fn test_source_creation() {
let data = b"hello world";
let cursor = Cursor::new(data);
let source = Source::new(cursor);
assert_eq!(source.index, 0);
assert!(source.stack.is_empty());
}
#[test]
fn test_source_peek1() {
let data = b"hello";
let cursor = Cursor::new(data);
let mut source = Source::new(cursor);
let byte = source.peek1().unwrap();
assert_eq!(byte, b'h');
assert_eq!(source.index, 0);
let byte2 = source.peek1().unwrap();
assert_eq!(byte2, b'h');
}
#[test]
fn test_source_peek1_empty() {
let data = b"";
let cursor = Cursor::new(data);
let mut source = Source::new(cursor);
let result = source.peek1();
assert!(matches!(result, Err(Error::NoMatch)));
}
#[test]
fn test_source_peek_multiple() {
let data = b"hello world";
let cursor = Cursor::new(data);
let mut source = Source::new(cursor);
let bytes = source.peek(5).unwrap();
assert_eq!(bytes, b"hello");
assert_eq!(source.index, 0);
let bytes = source.peek(11).unwrap();
assert_eq!(bytes, b"hello world");
}
#[test]
fn test_source_peek_beyond_end() {
let data = b"hi";
let cursor = Cursor::new(data);
let mut source = Source::new(cursor);
let result = source.peek(5);
assert!(matches!(result, Err(Error::NoMatch)));
}
#[test]
fn test_source_advance() {
let data = b"hello";
let cursor = Cursor::new(data);
let mut source = Source::new(cursor);
source.advance(2);
assert_eq!(source.index, 2);
let byte = source.peek1().unwrap();
assert_eq!(byte, b'l');
source.advance(3);
assert_eq!(source.index, 5);
let result = source.peek1();
assert!(matches!(result, Err(Error::NoMatch)));
}
#[test]
fn test_source_read() {
let data = b"hello world";
let cursor = Cursor::new(data);
let mut source = Source::new(cursor);
let bytes = source.read(5).unwrap();
assert_eq!(bytes, b"hello");
assert_eq!(source.index, 5);
let byte = source.peek1().unwrap();
assert_eq!(byte, b' ');
let bytes = source.read(6).unwrap();
assert_eq!(bytes, b" world");
assert_eq!(source.index, 11);
}
#[test]
fn test_source_read_beyond_end() {
let data = b"hi";
let cursor = Cursor::new(data);
let mut source = Source::new(cursor);
let result = source.read(5);
assert!(matches!(result, Err(Error::NoMatch)));
assert_eq!(source.index, 0); }
#[test]
fn test_source_push_pop() {
let data = b"hello";
let cursor = Cursor::new(data);
let mut source = Source::new(cursor);
source.advance(2);
assert_eq!(source.index, 2);
source.push();
assert_eq!(source.stack.len(), 1);
source.advance(2);
assert_eq!(source.index, 4);
source.pop();
assert_eq!(source.index, 2);
assert_eq!(source.stack.len(), 0);
}
#[test]
fn test_source_push_commit() {
let data = b"hello";
let cursor = Cursor::new(data);
let mut source = Source::new(cursor);
source.advance(2);
source.push();
source.advance(2);
assert_eq!(source.index, 4);
source.commit();
assert_eq!(source.index, 4); assert_eq!(source.stack.len(), 0);
}
#[test]
fn test_source_nested_push_pop() {
let data = b"hello world";
let cursor = Cursor::new(data);
let mut source = Source::new(cursor);
source.advance(2);
source.push();
source.advance(3);
source.push();
source.advance(2);
assert_eq!(source.index, 7);
source.pop();
assert_eq!(source.index, 5);
source.pop();
assert_eq!(source.index, 2);
}
#[test]
fn test_source_empty_stack_pop() {
let data = b"hello";
let cursor = Cursor::new(data);
let mut source = Source::new(cursor);
source.advance(3);
source.pop(); assert_eq!(source.index, 0);
}
#[test]
fn test_unit_parser() {
let data = b"anything";
let cursor = Cursor::new(data);
let mut source = Source::new(cursor);
let unit_parser = ();
parse(unit_parser, &mut source).unwrap();
assert_eq!(source.index, 0); }
#[test]
fn test_unit_parser_empty_input() {
let data = b"";
let cursor = Cursor::new(data);
let mut source = Source::new(cursor);
let unit_parser = ();
parse(unit_parser, &mut source).unwrap();
}
#[test]
fn test_parse_global_function() {
let data = b"test";
let cursor = Cursor::new(data);
let mut source = Source::new(cursor);
let unit_parser = ();
parse(unit_parser, &mut source).unwrap();
}
#[test]
fn test_parse_with_cache_global_function() {
let data = b"test";
let cursor = Cursor::new(data);
let mut source = Source::new(cursor);
let mut cache = NoCache;
let unit_parser = ();
parse_with_cache(unit_parser, &mut source, &mut cache).unwrap();
}
#[test]
fn test_source_position_management() {
let data = b"0123456789";
let cursor = Cursor::new(data);
let mut source = Source::new(cursor);
for i in 0..10 {
let byte = source.peek1().unwrap();
assert_eq!(byte, b'0' + i as u8);
source.advance(1);
assert_eq!(source.index, i + 1);
}
let result = source.peek1();
assert!(matches!(result, Err(Error::NoMatch)));
}
#[test]
fn test_source_large_advance() {
let data = b"hello";
let cursor = Cursor::new(data);
let mut source = Source::new(cursor);
source.advance(1000);
assert_eq!(source.index, 1000);
let result = source.peek1();
assert!(matches!(result, Err(Error::NoMatch)));
}
#[test]
fn test_source_zero_read() {
let data = b"hello";
let cursor = Cursor::new(data);
let mut source = Source::new(cursor);
let bytes = source.read(0).unwrap();
assert_eq!(bytes, b"");
assert_eq!(source.index, 0);
}
#[test]
fn test_source_zero_peek() {
let data = b"hello";
let cursor = Cursor::new(data);
let mut source = Source::new(cursor);
let bytes = source.peek(0).unwrap();
assert_eq!(bytes, b"");
assert_eq!(source.index, 0);
}
#[test]
fn test_id_implementation_literal_parsers() {
use crate::literal::Literal;
let literal1 = Literal::from_str("hello");
let literal2 = Literal::from_str("world");
assert_ne!(
<Literal as crate::parser::Parser<()>>::id(&literal1),
<Literal as crate::parser::Parser<()>>::id(&literal2),
"Different Literal instances should have different IDs to avoid cache conflicts"
);
let literal3 = Literal::from_str("hello");
assert_eq!(
<Literal as crate::parser::Parser<()>>::id(&literal1),
<Literal as crate::parser::Parser<()>>::id(&literal3),
"Literal instances with same content should have same ID for cache efficiency"
);
}
#[test]
fn test_id_implementation_unit_parser() {
let unit1 = ();
let unit2 = ();
assert_eq!(
<() as crate::parser::Parser<()>>::id(&unit1),
<() as crate::parser::Parser<()>>::id(&unit2),
"Unit parsers should have same ID since they're functionally identical"
);
}
#[test]
fn test_parser_caching_behavior() {
use crate::literal::Literal;
let data = b"hello";
let cursor = Cursor::new(data);
let mut source = Source::new(cursor);
let mut cache = BasicCache::new();
let literal = Literal::from_str("hello");
let result1 = parse_with_cache(literal.clone(), &mut source, &mut cache).unwrap();
assert_eq!(result1, b"hello".as_slice().into());
source.index = 0;
let result2 = parse_with_cache(literal, &mut source, &mut cache).unwrap();
assert_eq!(result2, b"hello".as_slice().into());
}
#[test]
fn test_arc_parser() {
use crate::literal::Literal;
let data = b"hello";
let cursor = Cursor::new(data);
let mut source = Source::new(cursor);
let literal = Arc::new(Literal::from_str("hello"));
let result = parse(literal, &mut source).unwrap();
assert_eq!(result, b"hello".as_slice().into());
}
#[test]
fn test_rc_parser() {
use crate::literal::Literal;
let data = b"hello";
let cursor = Cursor::new(data);
let mut source = Source::new(cursor);
let literal = Rc::new(Literal::from_str("hello"));
let result = parse(literal, &mut source).unwrap();
assert_eq!(result, b"hello".as_slice().into());
}
#[test]
fn test_arc_mutex_parser() {
use crate::literal::Literal;
let data = b"hello";
let cursor = Cursor::new(data);
let mut source = Source::new(cursor);
let literal = Arc::new(Mutex::new(Literal::from_str("hello")));
let result = parse(literal, &mut source).unwrap();
assert_eq!(result, b"hello".as_slice().into());
}
#[test]
fn test_arc_rwlock_parser() {
use crate::literal::Literal;
let data = b"hello";
let cursor = Cursor::new(data);
let mut source = Source::new(cursor);
let literal = Arc::new(RwLock::new(Literal::from_str("hello")));
let result = parse(literal, &mut source).unwrap();
assert_eq!(result, b"hello".as_slice().into());
}
#[test]
fn test_rc_refcell_parser() {
use crate::literal::Literal;
let data = b"hello";
let cursor = Cursor::new(data);
let mut source = Source::new(cursor);
let literal = Rc::new(RefCell::new(Literal::from_str("hello")));
let result = parse(literal, &mut source).unwrap();
assert_eq!(result, b"hello".as_slice().into());
}
#[test]
fn test_std_mutex_parser() {
use crate::literal::Literal;
let data = b"hello";
let cursor = Cursor::new(data);
let mut source = Source::new(cursor);
let literal = StdMutex::new(Literal::from_str("hello"));
let result = parse(literal, &mut source).unwrap();
assert_eq!(result, b"hello".as_slice().into());
}
#[test]
fn test_std_rwlock_parser() {
use crate::literal::Literal;
let data = b"hello";
let cursor = Cursor::new(data);
let mut source = Source::new(cursor);
let literal = StdRwLock::new(Literal::from_str("hello"));
let result = parse(literal, &mut source).unwrap();
assert_eq!(result, b"hello".as_slice().into());
}
#[test]
fn test_arc_std_mutex_parser() {
use crate::literal::Literal;
let data = b"hello";
let cursor = Cursor::new(data);
let mut source = Source::new(cursor);
let literal = Arc::new(StdMutex::new(Literal::from_str("hello")));
let result = parse(literal, &mut source).unwrap();
assert_eq!(result, b"hello".as_slice().into());
}
#[test]
fn test_arc_std_rwlock_parser() {
use crate::literal::Literal;
let data = b"hello";
let cursor = Cursor::new(data);
let mut source = Source::new(cursor);
let literal = Arc::new(StdRwLock::new(Literal::from_str("hello")));
let result = parse(literal, &mut source).unwrap();
assert_eq!(result, b"hello".as_slice().into());
}
#[test]
fn test_smart_pointer_parser_id_consistency() {
use crate::literal::Literal;
let base_literal = Literal::from_str("hello");
let arc_mutex = Arc::new(Mutex::new(Literal::from_str("hello")));
let arc_rwlock = Arc::new(RwLock::new(Literal::from_str("hello")));
let rc_refcell = Rc::new(RefCell::new(Literal::from_str("hello")));
assert_eq!(
<Literal as crate::parser::Parser<()>>::id(&base_literal),
<Arc<Mutex<Literal>> as crate::parser::Parser<()>>::id(&arc_mutex)
);
assert_eq!(
<Literal as crate::parser::Parser<()>>::id(&base_literal),
<Arc<RwLock<Literal>> as crate::parser::Parser<()>>::id(&arc_rwlock)
);
assert_eq!(
<Literal as crate::parser::Parser<()>>::id(&base_literal),
<Rc<RefCell<Literal>> as crate::parser::Parser<()>>::id(&rc_refcell)
);
}
#[test]
fn test_arc_weak_parser_alive() {
use crate::literal::Literal;
let data = b"hello";
let cursor = Cursor::new(data);
let mut source = Source::new(cursor);
let arc_literal = Arc::new(Literal::from_str("hello"));
let weak_literal = Arc::downgrade(&arc_literal);
assert_eq!(
<Arc<Literal> as crate::parser::Parser<()>>::id(&arc_literal),
<std::sync::Weak<Literal> as crate::parser::Parser<()>>::id(&weak_literal)
);
let result = parse(weak_literal, &mut source).unwrap();
assert_eq!(result, b"hello".as_slice().into());
}
#[test]
fn test_arc_weak_parser_dropped() {
use crate::literal::Literal;
let data = b"hello";
let cursor = Cursor::new(data);
let mut source = Source::new(cursor);
let weak_literal = {
let arc_literal = Arc::new(Literal::from_str("hello"));
Arc::downgrade(&arc_literal)
};
let result = parse(weak_literal, &mut source);
assert!(matches!(result, Err(Error::NoMatch)));
}
#[test]
fn test_rc_weak_parser_alive() {
use crate::literal::Literal;
let data = b"hello";
let cursor = Cursor::new(data);
let mut source = Source::new(cursor);
let rc_literal = Rc::new(Literal::from_str("hello"));
let weak_literal = Rc::downgrade(&rc_literal);
assert_eq!(
<Rc<Literal> as crate::parser::Parser<()>>::id(&rc_literal),
<std::rc::Weak<Literal> as crate::parser::Parser<()>>::id(&weak_literal)
);
let result = parse(weak_literal, &mut source).unwrap();
assert_eq!(result, b"hello".as_slice().into());
}
#[test]
fn test_rc_weak_parser_dropped() {
use crate::literal::Literal;
let data = b"hello";
let cursor = Cursor::new(data);
let mut source = Source::new(cursor);
let weak_literal = {
let rc_literal = Rc::new(Literal::from_str("hello"));
Rc::downgrade(&rc_literal)
};
let result = parse(weak_literal, &mut source);
assert!(matches!(result, Err(Error::NoMatch)));
}
#[test]
fn test_arc_weak_mutex_parser_alive() {
use crate::literal::Literal;
let data = b"hello";
let cursor = Cursor::new(data);
let mut source = Source::new(cursor);
let arc_literal = Arc::new(Mutex::new(Literal::from_str("hello")));
let weak_literal = Arc::downgrade(&arc_literal);
assert_eq!(
<Arc<Mutex<Literal>> as crate::parser::Parser<()>>::id(&arc_literal),
<std::sync::Weak<Mutex<Literal>> as crate::parser::Parser<()>>::id(&weak_literal)
);
let result = parse(weak_literal, &mut source).unwrap();
assert_eq!(result, b"hello".as_slice().into());
}
#[test]
fn test_arc_weak_mutex_parser_dropped() {
use crate::literal::Literal;
let data = b"hello";
let cursor = Cursor::new(data);
let mut source = Source::new(cursor);
let weak_literal = {
let arc_literal = Arc::new(Mutex::new(Literal::from_str("hello")));
Arc::downgrade(&arc_literal)
};
let result = parse(weak_literal, &mut source);
assert!(matches!(result, Err(Error::NoMatch)));
}
#[test]
fn test_arc_weak_rwlock_parser_alive() {
use crate::literal::Literal;
let data = b"hello";
let cursor = Cursor::new(data);
let mut source = Source::new(cursor);
let arc_literal = Arc::new(RwLock::new(Literal::from_str("hello")));
let weak_literal = Arc::downgrade(&arc_literal);
assert_eq!(
<Arc<RwLock<Literal>> as crate::parser::Parser<()>>::id(&arc_literal),
<std::sync::Weak<RwLock<Literal>> as crate::parser::Parser<()>>::id(&weak_literal)
);
let result = parse(weak_literal, &mut source).unwrap();
assert_eq!(result, b"hello".as_slice().into());
}
#[test]
fn test_rc_weak_refcell_parser_alive() {
use crate::literal::Literal;
let data = b"hello";
let cursor = Cursor::new(data);
let mut source = Source::new(cursor);
let rc_literal = Rc::new(RefCell::new(Literal::from_str("hello")));
let weak_literal = Rc::downgrade(&rc_literal);
assert_eq!(
<Rc<RefCell<Literal>> as crate::parser::Parser<()>>::id(&rc_literal),
<std::rc::Weak<RefCell<Literal>> as crate::parser::Parser<()>>::id(&weak_literal)
);
let result = parse(weak_literal, &mut source).unwrap();
assert_eq!(result, b"hello".as_slice().into());
}
#[test]
fn test_rc_weak_refcell_parser_dropped() {
use crate::literal::Literal;
let data = b"hello";
let cursor = Cursor::new(data);
let mut source = Source::new(cursor);
let weak_literal = {
let rc_literal = Rc::new(RefCell::new(Literal::from_str("hello")));
Rc::downgrade(&rc_literal)
};
let result = parse(weak_literal, &mut source);
assert!(matches!(result, Err(Error::NoMatch)));
}
}