use crate::codec::{Codec, CodecError, CodecResult, Reader};
use crate::types::{VarIntList, EMPTY_OPTIONAL};
use crate::Blob;
use std::fmt::Debug;
#[derive(Debug, Eq, PartialEq)]
pub struct Tag(pub String, pub ValueType);
pub type TaggedValue<T> = (String, T);
impl<T: Codec> Codec for TaggedValue<T> {
fn encode(&self, output: &mut Vec<u8>) {
Tag::encode_from(&self.0, &T::value_type(), output);
T::encode(&self.1, output);
}
fn decode(reader: &mut Reader) -> CodecResult<Self> {
let tag = Tag::decode(reader)?;
let expected_type = T::value_type();
let actual_type = tag.1;
if actual_type != expected_type {
return Err(CodecError::UnexpectedType(expected_type, actual_type));
}
let value = T::decode(reader)?;
Ok((tag.0, value))
}
}
impl Tag {
pub fn expect<T: Codec>(reader: &mut Reader, tag: &str) -> CodecResult<T> {
let expected_type = T::value_type();
loop {
let decoded = match Self::decode(reader) {
Ok(tag) => tag,
Err(CodecError::NotEnoughBytes(_, _, _)) => {
return Err(CodecError::MissingField(tag.to_string()))
}
Err(err) => return Err(err),
};
if decoded.0.ne(tag) {
Self::discard_type(&decoded.1, reader)?;
continue;
}
if decoded.1.ne(&expected_type) {
return Err(CodecError::UnexpectedFieldType(
tag.to_string(),
expected_type.clone(),
decoded.1.clone(),
));
}
return T::decode(reader);
}
}
pub fn try_expect<T: Codec>(reader: &mut Reader, tag: &str) -> CodecResult<Option<T>> {
reader.mark();
match Self::expect(reader, tag) {
Err(CodecError::MissingField(_)) => {
reader.reset_marker();
Ok(None)
}
Ok(value) => Ok(Some(value)),
Err(err) => Err(err),
}
}
pub fn take_two(reader: &mut Reader) -> CodecResult<()> {
let byte = reader.take_one()?;
if byte != 2 {
reader.step_back();
}
Ok(())
}
pub fn stringify(reader: &mut Reader, out: &mut String, indent: usize) -> CodecResult<()> {
while reader.remaining() > 0 {
match Self::create_string_tag(reader, out, indent) {
Ok(_) => {}
Err(err) => {
out.push_str(&format!(
"... remaining {}, cause: {:?}",
reader.remaining(),
err
));
break;
}
};
}
Ok(())
}
pub fn create_string_tag(
reader: &mut Reader,
out: &mut String,
indent: usize,
) -> CodecResult<()> {
let tag = Tag::decode(reader)?;
out.push_str(&" ".repeat(indent));
out.push_str(&format!("\"{}\": ", &tag.0));
return match Self::create_string_type(reader, out, indent, &tag.1) {
Ok(_) => {
out.push_str(",\n");
Ok(())
}
Err(err) => {
out.push_str("...");
Err(err)
}
};
}
pub fn create_string_type(
reader: &mut Reader,
out: &mut String,
indent: usize,
ty: &ValueType,
) -> CodecResult<()> {
match ty {
ValueType::VarInt => {
let value = u64::decode(reader)?;
out.push_str(&value.to_string());
}
ValueType::String => {
let value = String::decode(reader)?;
out.push('"');
out.push_str(&value);
out.push('"');
}
ValueType::Blob => {
let value = Blob::decode(reader)?;
out.push_str("Blob[");
for b in value.0 {
out.push_str(&format!("0x{:X}", b));
}
out.push(']');
}
ValueType::Group => {
out.push_str("Group {\n");
let mut is_two = false;
loop {
let next_byte = reader.take_one()?;
if next_byte == 0 {
break;
}
if next_byte != 2 {
reader.step_back();
} else {
is_two = true;
}
Self::create_string_tag(reader, out, indent + 1)?;
}
out.push_str(&" ".repeat(indent));
out.push_str("}");
if is_two {
out.push_str(" (2)");
}
}
ValueType::List => {
let value_type = ValueType::decode(reader)?;
let length = usize::decode(reader)?;
let nl = match value_type {
ValueType::Map | ValueType::Group => true,
_ => false,
};
out.push_str(&format!("List<{:?}> ", value_type));
out.push('[');
if nl {
out.push('\n')
}
for _ in 0..length {
if nl {
out.push_str(&" ".repeat(indent + 1));
}
Self::create_string_type(reader, out, indent + 1, &value_type)?;
out.push_str(", ");
if nl {
out.push('\n')
}
}
if nl {
out.push_str(&" ".repeat(indent));
}
out.push(']');
}
ValueType::Map => {
let key_type = ValueType::decode(reader)?;
let value_type = ValueType::decode(reader)?;
let length = usize::decode(reader)?;
out.push_str(&format!("Map<{:?}, {:?}> ", key_type, value_type));
out.push_str("{\n");
for _ in 0..length {
out.push_str(&" ".repeat(indent + 1));
Self::create_string_type(reader, out, indent + 1, &key_type)?;
out.push_str(": ");
Self::create_string_type(reader, out, indent + 1, &value_type)?;
out.push('\n')
}
out.push_str(&" ".repeat(indent));
out.push('}');
}
ValueType::Optional => {
let ty = reader.take_one()?;
if ty != EMPTY_OPTIONAL {
out.push_str("Optional(");
let tag = Tag::decode(reader)?;
out.push_str(&format!("\"{}\", {:?}: ", &tag.0, ty));
Self::create_string_type(reader, out, indent + 1, &tag.1)?;
out.push_str(&" ".repeat(indent));
out.push_str(")")
} else {
out.push_str("Optional(Empty)");
}
}
ValueType::VarIntList => {
let value = VarIntList::<usize>::decode(reader)?;
out.push_str("VarList[");
for b in value.0 {
out.push_str(&format!("0x{:X}", b));
}
out.push(']');
}
ValueType::Pair => {
let pair = <(usize, usize)>::decode(reader)?;
out.push_str(&format!("({}, {})", &pair.0, &pair.1));
}
ValueType::Triple => {
let value = <(usize, usize, usize)>::decode(reader)?;
out.push_str(&format!("({}, {}, {})", &value.0, &value.1, &value.2));
}
ValueType::Float => {
let value = f32::decode(reader)?;
out.push_str(&value.to_string());
}
ValueType::Unknown(_) => return Err(CodecError::Other("Unknown tag type")),
}
Ok(())
}
pub fn discard_tag(reader: &mut Reader) -> CodecResult<()> {
let tag = Tag::decode(reader)?;
Self::discard_type(&tag.1, reader)
}
pub fn discard_type(ty: &ValueType, reader: &mut Reader) -> CodecResult<()> {
match ty {
ValueType::VarInt => usize::skip(reader)?,
ValueType::String => String::skip(reader)?,
ValueType::Blob => <Vec<u8>>::skip(reader)?,
ValueType::Group => Self::discard_group(reader)?,
ValueType::List => {
let new_ty = ValueType::decode(reader)?;
let length = usize::decode(reader)?;
for _ in 0..length {
Self::discard_type(&new_ty, reader)?;
}
}
ValueType::Map => {
let key_ty = ValueType::decode(reader)?;
let value_ty = ValueType::decode(reader)?;
let length = usize::decode(reader)?;
for _ in 0..length {
Self::discard_type(&key_ty, reader)?;
Self::discard_type(&value_ty, reader)?;
}
}
ValueType::Optional => {
let ty = reader.take_one()?;
if ty != EMPTY_OPTIONAL {
Self::discard_tag(reader)?;
}
}
ValueType::VarIntList => VarIntList::<usize>::skip(reader)?,
ValueType::Pair => <(usize, usize)>::skip(reader)?,
ValueType::Triple => <(usize, usize, usize)>::skip(reader)?,
ValueType::Float => f32::skip(reader)?,
ValueType::Unknown(_) => {}
};
Ok(())
}
pub fn discard_group(reader: &mut Reader) -> CodecResult<()> {
while let Ok(next_byte) = reader.take_one() {
if next_byte == 0 {
break;
}
reader.step_back();
Self::discard_tag(reader)?;
}
Ok(())
}
pub fn encode_from(tag: &str, value_type: &ValueType, output: &mut Vec<u8>) {
Self::encode_tag(tag, output);
value_type.encode(output);
}
pub fn encode_tag(tag: &str, output: &mut Vec<u8>) {
let mut out: [u8; 3] = [0, 0, 0];
let mut input: [u8; 4] = [0, 0, 0, 0];
let mut bytes = tag.bytes();
for i in 0..4 {
input[i] = match bytes.next() {
None => 0,
Some(value) => value,
}
}
out[0] |= (input[0] & 0x40) << 1;
out[0] |= (input[0] & 0x10) << 2;
out[0] |= (input[0] & 0x0F) << 2;
out[0] |= (input[1] & 0x40) >> 5;
out[0] |= (input[1] & 0x10) >> 4;
out[1] |= (input[1] & 0x0F) << 4;
out[1] |= (input[2] & 0x40) >> 3;
out[1] |= (input[2] & 0x10) >> 2;
out[1] |= (input[2] & 0x0C) >> 2;
out[2] |= (input[2] & 0x03) << 6;
out[2] |= (input[3] & 0x40) >> 1;
out[2] |= input[3] & 0x1F;
output.extend_from_slice(&out);
}
}
impl Codec for Tag {
fn encode(&self, output: &mut Vec<u8>) {
Tag::encode_from(&self.0, &self.1, output);
}
fn decode(reader: &mut Reader) -> CodecResult<Self> {
let tag: &[u8; 4] = reader
.take(4)?
.try_into()
.map_err(|_| CodecError::UnknownError)?;
let value_type = ValueType::from_value(tag[3]);
let mut output: [u8; 4] = [0, 0, 0, 0];
output[0] |= (tag[0] & 0x80) >> 1;
output[0] |= (tag[0] & 0x40) >> 2;
output[0] |= (tag[0] & 0x30) >> 2;
output[0] |= (tag[0] & 0x0C) >> 2;
output[1] |= (tag[0] & 0x02) << 5;
output[1] |= (tag[0] & 0x01) << 4;
output[1] |= (tag[1] & 0xF0) >> 4;
output[2] |= (tag[1] & 0x08) << 3;
output[2] |= (tag[1] & 0x04) << 2;
output[2] |= (tag[1] & 0x03) << 2;
output[2] |= (tag[2] & 0xC0) >> 6;
output[3] |= (tag[2] & 0x20) << 1;
output[3] |= tag[2] & 0x1F;
let mut out = String::new();
for value in output {
match value {
0 => {}
value => out.push(char::from(value)),
}
}
Ok(Tag(out, value_type))
}
}
#[derive(Debug, PartialEq, Eq, Clone)]
pub enum ValueType {
VarInt,
String,
Blob,
Group,
List,
Map,
Optional,
VarIntList,
Pair,
Triple,
Float,
Unknown(u8),
}
impl Codec for ValueType {
fn encode(&self, output: &mut Vec<u8>) {
output.push(self.value());
}
fn decode(reader: &mut Reader) -> CodecResult<Self> {
reader.take_one().map(ValueType::from_value)
}
}
impl ValueType {
pub fn value(&self) -> u8 {
match self {
ValueType::VarInt => 0x0,
ValueType::String => 0x1,
ValueType::Blob => 0x2,
ValueType::Group => 0x3,
ValueType::List => 0x4,
ValueType::Map => 0x5,
ValueType::Optional => 0x6,
ValueType::VarIntList => 0x7,
ValueType::Pair => 0x8,
ValueType::Triple => 0x9,
ValueType::Float => 0xA,
ValueType::Unknown(value) => *value,
}
}
pub fn from_value(value: u8) -> ValueType {
match value {
0x0 => ValueType::VarInt,
0x1 => ValueType::String,
0x2 => ValueType::Blob,
0x3 => ValueType::Group,
0x4 => ValueType::List,
0x5 => ValueType::Map,
0x6 => ValueType::Optional,
0x7 => ValueType::VarIntList,
0x8 => ValueType::Pair,
0x9 => ValueType::Triple,
0xA => ValueType::Float,
value => ValueType::Unknown(value),
}
}
}
#[cfg(test)]
mod test {
use crate::codec::{Codec, Reader};
use crate::tag::{Tag, ValueType};
#[test]
fn test_read_write() {
let mut out = Vec::new();
let tag_in = Tag(String::from("TEST"), ValueType::String);
tag_in.encode(&mut out);
let mut reader = Reader::new(&out);
let tag = Tag::decode(&mut reader).unwrap();
assert_eq!(tag_in, tag)
}
#[test]
fn test_tag() {
let tag_out = Tag(String::from("PORT"), ValueType::VarInt);
let mut out = Vec::new();
tag_out.encode(&mut out);
println!("{out:?}")
}
#[test]
fn parse_tag() {
let tag = [226, 75, 179, 0];
let mut reader = Reader::new(&tag);
let tag = Tag::decode(&mut reader);
print!("{tag:?}")
}
}