1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142
use crate::Tags; type Result<T> = std::result::Result<T, ParseError>; /** Tries to decode one message, returning the amount of remaining data in the input # Example ## A single message ```rust # use twitchchat::*; # use std::borrow::Cow; let input = ":test!test@test JOIN #museun\r\n"; let (pos, message) = decode_one(&input).unwrap(); assert_eq!(pos, 0); // no more messages were found let expected = messages::Raw { raw: Cow::Borrowed(":test!test@test JOIN #museun\r\n"), tags: Tags::default(), prefix: Some(decode::Prefix::User { nick: Cow::Borrowed("test") }), command: Cow::Borrowed("JOIN"), args: Cow::Borrowed("#museun"), data: None, }; assert_eq!(message, expected); ``` # Multiple messages ```rust # use twitchchat::*; # use std::borrow::Cow; let input = ":test!test@test JOIN #museun\r\n:test!test@test JOIN #shaken_bot\r\n"; let (pos, message) = decode_one(&input).unwrap(); assert_eq!(pos, 30); // another message probably starts at offset '30' let expected = messages::Raw { raw: Cow::Borrowed(":test!test@test JOIN #museun\r\n"), tags: Tags::default(), prefix: Some(decode::Prefix::User { nick: Cow::Borrowed("test") }), command: Cow::Borrowed("JOIN"), args: Cow::Borrowed("#museun"), data: None, }; assert_eq!(message, expected); // continue from where it left off let (pos, message) = decode_one(&input[pos..]).unwrap(); assert_eq!(pos, 0); // no more messages were found let expected = messages::Raw { raw: Cow::Borrowed(":test!test@test JOIN #shaken_bot\r\n"), tags: Tags::default(), prefix: Some(decode::Prefix::User { nick: Cow::Borrowed("test") }), command: Cow::Borrowed("JOIN"), args: Cow::Borrowed("#shaken_bot"), data: None, }; assert_eq!(message, expected); ``` */ pub fn decode_one<'t>(input: &'t str) -> Result<(usize, Message<'t>)> { let pos = input .find("\r\n") .ok_or_else(|| ParseError::IncompleteMessage { pos: 0 })?; let next = if pos + 2 == input.len() { 0 } else { pos + 2 }; Message::parse(&input[..pos + 2]).map(|msg| (next, msg)) } /** Tries to decode potentially many messages from this input string # Example ```rust # use twitchchat::*; # use std::borrow::Cow; let input = ":test!test@test JOIN #museun\r\n:test!test@test JOIN #shaken_bot\r\n"; let expected = &[ messages::Raw { raw: Cow::Borrowed(":test!test@test JOIN #museun\r\n"), tags: Tags::default(), prefix: Some(decode::Prefix::User { nick: Cow::Borrowed("test") }), command: Cow::Borrowed("JOIN"), args: Cow::Borrowed("#museun"), data: None, }, messages::Raw { raw: Cow::Borrowed(":test!test@test JOIN #shaken_bot\r\n"), tags: Tags::default(), prefix: Some(decode::Prefix::User { nick: Cow::Borrowed("test") }), command: Cow::Borrowed("JOIN"), args: Cow::Borrowed("#shaken_bot"), data: None, }, ]; for (message, expected) in decode(&input).zip(expected.iter()) { let msg = message.expect("valid message"); assert_eq!(msg, *expected); } ``` */ pub const fn decode(input: &str) -> DecodeIter<'_> { DecodeIter(ParseIter::new(input)) } /// An iterator over decoded messages pub struct DecodeIter<'a>(ParseIter<'a>); impl<'a> Iterator for DecodeIter<'a> { type Item = Result<Message<'a>>; #[inline] fn next(&mut self) -> Option<Self::Item> { self.0.next() } } impl<'a> std::iter::FusedIterator for DecodeIter<'a> {} impl<'a> std::fmt::Debug for DecodeIter<'a> { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { f.debug_struct("DebugIter").finish() } } mod parser; use parser::*; mod message; pub use message::*; mod prefix; pub use prefix::*; mod error; pub use error::*; #[cfg(test)] mod tests;