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
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::*;
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: ":test!test@test JOIN #museun\r\n",
    tags: Tags::default(),
    prefix: Some(decode::Prefix::User { nick: "test" }),
    command: "JOIN",
    args: "#museun",
    data: None,
};
assert_eq!(message, expected);
```

# Multiple messages
```rust
# use twitchchat::*;
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: ":test!test@test JOIN #museun\r\n",
    tags: Tags::default(),
    prefix: Some(decode::Prefix::User { nick: "test" }),
    command: "JOIN",
    args: "#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: ":test!test@test JOIN #shaken_bot\r\n",
    tags: Tags::default(),
    prefix: Some(decode::Prefix::User { nick: "test" }),
    command: "JOIN",
    args: "#shaken_bot",
    data: None,
};
assert_eq!(message, expected);
```
*/
pub fn decode_one(input: &str) -> Result<(usize, Message<&'_ str>)> {
    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::*;
let input = ":test!test@test JOIN #museun\r\n:test!test@test JOIN #shaken_bot\r\n";

let expected = &[
    messages::Raw {
        raw: ":test!test@test JOIN #museun\r\n",
        tags: Tags::default(),
        prefix: Some(decode::Prefix::User { nick: "test" }),
        command: "JOIN",
        args: "#museun",
        data: None,
    },
    messages::Raw {
        raw: ":test!test@test JOIN #shaken_bot\r\n",
        tags: Tags::default(),
        prefix: Some(decode::Prefix::User { nick: "test" }),
        command: "JOIN",
        args: "#shaken_bot",
        data: None,
    },
];

for (message, expected) in decode(&input).zip(expected.iter()) {
    let msg = message.expect("valid message");
    assert_eq!(msg, *expected);
}
```
*/
pub fn decode(input: &str) -> impl Iterator<Item = Result<Message<&'_ str>>> + '_ {
    ParseIter::new(input)
}

mod parser;
use parser::*;

mod message;
pub use message::*;

mod prefix;
pub use prefix::*;

mod error;
pub use error::*;

#[cfg(test)]
mod tests;