yfunc_rust/
ybytes.rs

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
use std::{fmt, fs::File, io::Read};

use serde::{de::{self, Visitor}, Deserialize, Deserializer, Serialize, Serializer};
use base64::prelude::*;
use crate::prelude::*;

#[derive(Debug, Clone)]
pub struct YBytes(Vec<u8>);

impl YBytes {

    pub fn new(data: Vec<u8>) -> YBytes {
        YBytes(data)
    }

    pub fn data(&self) -> &Vec<u8> {
        &self.0
    }

    pub fn into_vec(self) -> Vec<u8> {
        self.0
    }

    pub fn length(&self) -> usize {
        self.0.len()
    }

    pub fn md5(&self) -> String {
        format!("{:x}", md5::compute(&self.0))
    }

    pub fn to_str(&self) -> YRes<String> {
        String::from_utf8(self.0.clone()).map_err(|e|
            err!("deserialize YBytes as utf-8 text failed").trace(
                ctx!("deserialize YBytes as utf-8 text: String::from_utf8() failed", e)
            )
        )
    }

    pub fn base64(&self) -> String {
        BASE64_STANDARD.encode(&self.0)
    }

    pub fn from_base64(base64_str: &str) -> YRes<YBytes> {
        let data = BASE64_STANDARD.decode(base64_str).map_err(|e| 
            err!("build YBytes from base64 string failed").trace(
                ctx!("build YBytes from base64 string: -> BASE64_STANDARD.decode failed", e)
            )
        )?;
        Ok(YBytes(data))
    }

    pub fn open_file(file_path: &str) -> YRes<YBytes> {
        let mut file = File::open(file_path).map_err(|e|
            err!("build YBytes from file content failed").trace(
                ctx!("build YBytes from file content -> open file: File::open failed", file_path, e)
            )
        )?;
        let mut bytes = Vec::new();
        file.read_to_end(&mut bytes).map_err(|e|
            err!("build YBytes from file content failed").trace(
                ctx!("build YBytes from file content -> read file content: file.read_to_end failed", file_path, e)
            )
        )?;
        Ok(YBytes::new(bytes))
    }

}

impl Serialize for YBytes {
    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error> where S: Serializer {
        serializer.serialize_str(&self.base64()) 
    }
}

impl<'de> Deserialize<'de> for YBytes {
    fn deserialize<D>(deserializer: D) -> Result<Self, D::Error> where D: Deserializer<'de> {
        struct YBytesVisitor;
        impl<'de> Visitor<'de> for YBytesVisitor {
            type Value = YBytes;
            fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
                formatter.write_str("a base64 encoded string")
            }
            fn visit_str<E>(self, value: &str) -> Result<YBytes, E> where E: de::Error {
                BASE64_STANDARD.decode(value).map(YBytes).map_err(de::Error::custom)
            }
        }
        deserializer.deserialize_str(YBytesVisitor)
    }
}