cfx_rpc_primitives/
bytes.rs

1// Copyright 2015-2018 Parity Technologies (UK) Ltd.
2// This file is part of Parity.
3
4// Parity is free software: you can redistribute it and/or modify
5// it under the terms of the GNU General Public License as published by
6// the Free Software Foundation, either version 3 of the License, or
7// (at your option) any later version.
8
9// Parity is distributed in the hope that it will be useful,
10// but WITHOUT ANY WARRANTY; without even the implied warranty of
11// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12// GNU General Public License for more details.
13
14// You should have received a copy of the GNU General Public License
15// along with Parity.  If not, see <http://www.gnu.org/licenses/>.
16
17// Copyright 2019 Conflux Foundation. All rights reserved.
18// Conflux is free software and distributed under GNU General Public License.
19// See http://www.gnu.org/licenses/
20
21//! Serializable wrapper around vector of bytes
22
23use core::{
24    borrow::Borrow,
25    ops::{Deref, DerefMut},
26};
27use rustc_hex::{FromHex, ToHex};
28use serde::{
29    de::{Error, Visitor},
30    Deserialize, Deserializer, Serialize, Serializer,
31};
32use std::fmt;
33
34/// Wrapper structure around vector of bytes.
35#[derive(Debug, PartialEq, Eq, Default, Hash, Clone)]
36#[allow(dead_code)]
37pub struct Bytes(pub Vec<u8>);
38
39impl Bytes {
40    /// Simple constructor.
41    pub fn new(bytes: Vec<u8>) -> Bytes { Bytes(bytes) }
42
43    /// Convert back to vector
44    #[allow(dead_code)]
45    pub fn into_vec(self) -> Vec<u8> { self.0 }
46}
47
48impl From<Vec<u8>> for Bytes {
49    fn from(bytes: Vec<u8>) -> Bytes { Bytes(bytes) }
50}
51
52impl Into<Vec<u8>> for Bytes {
53    fn into(self) -> Vec<u8> { self.0 }
54}
55
56impl Deref for Bytes {
57    type Target = Vec<u8>;
58
59    #[inline]
60    fn deref(&self) -> &Self::Target { &self.0 }
61}
62
63impl DerefMut for Bytes {
64    #[inline]
65    fn deref_mut(&mut self) -> &mut Self::Target { &mut self.0 }
66}
67
68impl AsRef<[u8]> for Bytes {
69    #[inline]
70    fn as_ref(&self) -> &[u8] { self.0.as_ref() }
71}
72
73impl Borrow<[u8]> for Bytes {
74    #[inline]
75    fn borrow(&self) -> &[u8] { self.as_ref() }
76}
77
78impl Serialize for Bytes {
79    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
80    where S: Serializer {
81        let mut serialized = "0x".to_owned();
82        serialized.push_str(self.0.to_hex::<String>().as_ref());
83        serializer.serialize_str(serialized.as_ref())
84    }
85}
86
87impl<'a> Deserialize<'a> for Bytes {
88    fn deserialize<D>(deserializer: D) -> Result<Bytes, D::Error>
89    where D: Deserializer<'a> {
90        deserializer.deserialize_any(BytesVisitor)
91    }
92}
93
94struct BytesVisitor;
95
96impl<'a> Visitor<'a> for BytesVisitor {
97    type Value = Bytes;
98
99    fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
100        write!(formatter, "a 0x-prefixed, hex-encoded vector of bytes")
101    }
102
103    fn visit_str<E>(self, value: &str) -> Result<Self::Value, E>
104    where E: Error {
105        if let (Some(s), true) =
106            (value.strip_prefix("0x"), value.len() & 1 == 0)
107        {
108            Ok(Bytes::new(FromHex::from_hex(s).map_err(|e| {
109                Error::custom(format!("Invalid hex: {}", e))
110            })?))
111        } else {
112            Err(Error::custom("Invalid bytes format. Expected a 0x-prefixed hex string with even length"))
113        }
114    }
115
116    fn visit_string<E>(self, value: String) -> Result<Self::Value, E>
117    where E: Error {
118        self.visit_str(value.as_ref())
119    }
120}
121
122#[cfg(test)]
123mod tests {
124    use rustc_hex::FromHex;
125    use serde_json;
126
127    use super::*;
128
129    #[test]
130    fn test_bytes_serialize() {
131        let bytes = Bytes("0123456789abcdef".from_hex().unwrap());
132        let serialized = serde_json::to_string(&bytes).unwrap();
133        assert_eq!(serialized, r#""0x0123456789abcdef""#);
134    }
135
136    #[test]
137    fn test_bytes_deserialize() {
138        let bytes1: Result<Bytes, serde_json::Error> =
139            serde_json::from_str(r#""""#);
140        let bytes2: Result<Bytes, serde_json::Error> =
141            serde_json::from_str(r#""0x123""#);
142        let bytes3: Result<Bytes, serde_json::Error> =
143            serde_json::from_str(r#""0xgg""#);
144
145        let bytes4: Bytes = serde_json::from_str(r#""0x""#).unwrap();
146        let bytes5: Bytes = serde_json::from_str(r#""0x12""#).unwrap();
147        let bytes6: Bytes = serde_json::from_str(r#""0x0123""#).unwrap();
148
149        assert!(bytes1.is_err());
150        assert!(bytes2.is_err());
151        assert!(bytes3.is_err());
152        assert_eq!(bytes4, Bytes(vec![]));
153        assert_eq!(bytes5, Bytes(vec![0x12]));
154        assert_eq!(bytes6, Bytes(vec![0x1, 0x23]));
155    }
156}