1use std::{fmt, fs::File, io::Read};
2
3use serde::{de::{self, Visitor}, Deserialize, Deserializer, Serialize, Serializer};
4use base64::prelude::*;
5use crate::prelude::*;
6
7#[derive(Debug, Clone)]
8pub struct YBytes(Vec<u8>);
9
10impl YBytes {
11
12 pub fn new(data: Vec<u8>) -> YBytes {
13 YBytes(data)
14 }
15
16 pub fn data(&self) -> &Vec<u8> {
17 &self.0
18 }
19
20 pub fn into_vec(self) -> Vec<u8> {
21 self.0
22 }
23
24 pub fn length(&self) -> usize {
25 self.0.len()
26 }
27
28 pub fn md5(&self) -> String {
29 format!("{:x}", md5::compute(&self.0))
30 }
31
32 pub fn to_str(&self) -> YRes<String> {
33 String::from_utf8(self.0.clone()).map_err(|e|
34 err!("deserialize YBytes as utf-8 text failed").trace(
35 ctx!("deserialize YBytes as utf-8 text: String::from_utf8() failed", e)
36 )
37 )
38 }
39
40 pub fn base64(&self) -> String {
41 BASE64_STANDARD.encode(&self.0)
42 }
43
44 pub fn from_base64(base64_str: &str) -> YRes<YBytes> {
45 let data = BASE64_STANDARD.decode(base64_str).map_err(|e|
46 err!("build YBytes from base64 string failed").trace(
47 ctx!("build YBytes from base64 string: -> BASE64_STANDARD.decode failed", e)
48 )
49 )?;
50 Ok(YBytes(data))
51 }
52
53 pub fn open_file(file_path: &str) -> YRes<YBytes> {
54 let mut file = File::open(file_path).map_err(|e|
55 err!("build YBytes from file content failed").trace(
56 ctx!("build YBytes from file content -> open file: File::open failed", file_path, e)
57 )
58 )?;
59 let mut bytes = Vec::new();
60 file.read_to_end(&mut bytes).map_err(|e|
61 err!("build YBytes from file content failed").trace(
62 ctx!("build YBytes from file content -> read file content: file.read_to_end failed", file_path, e)
63 )
64 )?;
65 Ok(YBytes::new(bytes))
66 }
67
68}
69
70impl Serialize for YBytes {
71 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error> where S: Serializer {
72 serializer.serialize_str(&self.base64())
73 }
74}
75
76impl<'de> Deserialize<'de> for YBytes {
77 fn deserialize<D>(deserializer: D) -> Result<Self, D::Error> where D: Deserializer<'de> {
78 struct YBytesVisitor;
79 impl<'de> Visitor<'de> for YBytesVisitor {
80 type Value = YBytes;
81 fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
82 formatter.write_str("a base64 encoded string")
83 }
84 fn visit_str<E>(self, value: &str) -> Result<YBytes, E> where E: de::Error {
85 BASE64_STANDARD.decode(value).map(YBytes).map_err(de::Error::custom)
86 }
87 }
88 deserializer.deserialize_str(YBytesVisitor)
89 }
90}
91