This patch makes it possible to use serde_bare in environments that
don't provide the rust std library.
e.g. embedded targets, web.
This patch does require that the target include the alloc library and
provide a suitable allocator.
Example usage is as follows:
[features]
default = ["std"]
std = ["serde_bare/std"]
alloc = ["serde_bare/alloc"]
[dependencies]
serde_bare = { version = "x.x", default-features = false }
The project can then be compiled for std with:
cargo build
And for no_std as:
cargo build --no-default-features --features="alloc"
---
Cargo.toml | 11 +++++++++--
src/compat.rs | 44 ++++++++++++++++++++++++++++++++++++++++++++
src/de.rs | 16 +++++++++++-----
src/error.rs | 12 +++++++-----
src/lib.rs | 26 ++++++++++++++++++++------
src/ser.rs | 6 +++++-
6 files changed, 96 insertions(+), 19 deletions(-)
create mode 100644 src/compat.rs
diff --git a/Cargo.toml b/Cargo.toml
index 448f839..78e1f47 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -1,6 +1,7 @@
[package]
name = "serde_bare"
version = "0.4.0"
+resolver = "2"
authors = ["Tadeo Kondrak <me@tadeo.ca>"]
license = "MIT OR Apache-2.0"
edition = "2018"
@@ -10,12 +11,18 @@ keywords = ["serde", "bare"]
categories = ["encoding"]
exclude = ["benches/go-reference"]
+[features]
+default = [ "std" ]
+std = ["serde/std"]
+alloc = ["core2/alloc", "core2/nightly", "serde/alloc", "serde/derive"]
+
[dependencies]
-serde = "1.0"
+serde = { version = "1.0", default-features = false, optional = true }
+core2 = { version = "0.3.2", default-features = false, optional = true }
[dev-dependencies]
serde_derive = "1.0"
-serde_bytes = "0.11"
+serde_bytes = { version = "0.11", default-features = false, features
= [ "alloc" ] }
criterion = "0.3"
[[bench]]
diff --git a/src/compat.rs b/src/compat.rs
new file mode 100644
index 0000000..fb6fe07
--- /dev/null
+++ b/src/compat.rs
@@ -0,0 +1,44 @@
+/// A facade around the various collections and primitives needed
+/// to support "std" and "no_std + alloc" targets.
+
+// std::boxed
+pub mod boxed {
+ #[cfg(feature = "std")]
+ pub use std::boxed::Box;
+ #[cfg(all(not(feature = "std"), feature = "alloc"))]
+ pub use alloc::boxed::Box;
+}
+
+// std::error::Error trait
+pub mod error {
+ #[cfg(feature = "std")]
+ pub use std::error::Error;
+ #[cfg(not(feature = "std"))]
+ pub trait Error: core::fmt::Debug + core::fmt::Display {
+ fn source(&self) -> Option<&(dyn Error + 'static)> {
+ None
+ }
+ }
+}
+
+// std::io
+#[cfg(feature = "std")]
+pub use std::io;
+#[cfg(not(feature = "std"))]
+pub use core2::io;
+
+// std::string
+pub mod string {
+ #[cfg(feature = "std")]
+ pub use std::string::{String, ToString};
+ #[cfg(all(not(feature = "std"), feature = "alloc"))]
+ pub use alloc::string::{String, ToString};
+}
+
+// std::vec
+pub mod vec {
+ #[cfg(feature = "std")]
+ pub use std::vec::Vec;
+ #[cfg(all(not(feature = "std"), feature = "alloc"))]
+ pub use alloc::vec::Vec;
+}
diff --git a/src/de.rs b/src/de.rs
index 8063944..bb1f28a 100644
--- a/src/de.rs
+++ b/src/de.rs
@@ -1,23 +1,28 @@
use crate::{error::Error, Uint};
use serde::de;
-use std::{
+use core::{
convert::TryInto,
i16, i32, i64, i8,
- io::{Cursor, Read},
str, u16, u32, u64, u8,
};
+use crate::compat::{
+ io::{self, Cursor, Read},
+ string::{String, ToString},
+ vec::Vec,
+};
/// Try and return a Vec<u8> of `len` bytes from a Reader
+#[cfg(any(feature = "std", feature = "alloc"))]
#[inline]
-fn read_bytes<R: Read>(reader: R, len: usize) -> Result<Vec<u8>,
std::io::Error> {
+fn read_bytes<R: Read>(reader: R, len: usize) -> Result<Vec<u8>, io::Error> {
// Allocate at most 4096 bytes to start with. Growing a Vec is
fairly efficient once you get out
// of the region of the first few hundred bytes.
let capacity = len.min(4096);
let mut buffer = Vec::with_capacity(capacity);
let read = reader.take(len as u64).read_to_end(&mut buffer)?;
if read < len {
- Err(std::io::Error::new(
- std::io::ErrorKind::UnexpectedEof,
+ Err(io::Error::new(
+ io::ErrorKind::UnexpectedEof,
"Unexpected EOF reading number of bytes expected in field prefix",
))
} else {
@@ -655,6 +660,7 @@ mod test {
#[test]
fn test_slice() {
+ use crate::compat::boxed::Box;
assert_eq!(
&[0u8; 4][..],
&*from_slice::<Box<[u8]>>(&[4, 0, 0, 0, 0]).unwrap()
diff --git a/src/error.rs b/src/error.rs
index 28937cc..a1762e3 100644
--- a/src/error.rs
+++ b/src/error.rs
@@ -1,10 +1,12 @@
use serde::{de, ser};
-use std::{
- fmt::{self, Display},
+use core::fmt::{self, Debug, Display};
+use crate::compat::{
+ error,
io,
+ string::{String, ToString}
};
-pub type Result<T> = std::result::Result<T, Error>;
+pub type Result<T> = core::result::Result<T, Error>;
#[derive(Debug)]
pub enum Error {
@@ -36,7 +38,7 @@ impl Display for Error {
fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
match self {
Error::Message(msg) => formatter.write_str(msg),
- Error::Io(e) => e.fmt(formatter),
+ Error::Io(e) => Debug::fmt(&e, formatter),
Error::AnyUnsupported => formatter.write_str("BARE does
not support any"),
Error::InvalidUtf8 => formatter.write_str("invalid utf-8
in string"),
Error::InvalidChar => formatter.write_str("invalid
unicode codepoint in char"),
@@ -46,4 +48,4 @@ impl Display for Error {
}
}
-impl std::error::Error for Error {}
+impl error::Error for Error {}
diff --git a/src/lib.rs b/src/lib.rs
index b8acc21..f7e5492 100644
--- a/src/lib.rs
+++ b/src/lib.rs
@@ -81,6 +81,18 @@
//! Serialized as a `uint` followed by the variant data.
//! The container name and variant name are ignored.
+#![cfg_attr(not(feature = "std"), no_std)]
+
+#[cfg(not(feature = "std"))]
+#[macro_use]
+extern crate core;
+
+#[cfg(feature = "alloc")]
+#[allow(unused_imports)]
+#[macro_use]
+extern crate alloc;
+
+mod compat;
pub mod de;
pub mod error;
pub mod ser;
@@ -102,7 +114,7 @@ impl Default for Uint {
}
impl serde::ser::Serialize for Uint {
- fn serialize<S>(&self, serializer: S) ->
std::result::Result<S::Ok, S::Error>
+ fn serialize<S>(&self, serializer: S) ->
core::result::Result<S::Ok, S::Error>
where
S: serde::ser::Serializer,
{
@@ -128,11 +140,11 @@ impl serde::ser::Serialize for Uint {
}
impl<'de> serde::de::Deserialize<'de> for Uint {
- fn deserialize<D>(deserializer: D) -> std::result::Result<Self, D::Error>
+ fn deserialize<D>(deserializer: D) -> core::result::Result<Self, D::Error>
where
D: serde::de::Deserializer<'de>,
{
- use std::fmt;
+ use core::fmt;
struct UintVisitor;
impl<'de> serde::de::Visitor<'de> for UintVisitor {
@@ -142,7 +154,7 @@ impl<'de> serde::de::Deserialize<'de> for Uint {
write!(formatter, "a BARE encoded variable-length integer")
}
- fn visit_seq<A>(self, mut seq: A) ->
std::result::Result<Self::Value, A::Error>
+ fn visit_seq<A>(self, mut seq: A) ->
core::result::Result<Self::Value, A::Error>
where
A: serde::de::SeqAccess<'de>,
{
@@ -189,7 +201,7 @@ impl Default for Int {
}
impl serde::ser::Serialize for Int {
- fn serialize<S>(&self, serializer: S) ->
std::result::Result<S::Ok, S::Error>
+ fn serialize<S>(&self, serializer: S) ->
core::result::Result<S::Ok, S::Error>
where
S: serde::ser::Serializer,
{
@@ -203,7 +215,7 @@ impl serde::ser::Serialize for Int {
}
impl<'de> serde::de::Deserialize<'de> for Int {
- fn deserialize<D>(deserializer: D) -> std::result::Result<Self, D::Error>
+ fn deserialize<D>(deserializer: D) -> core::result::Result<Self, D::Error>
where
D: serde::de::Deserializer<'de>,
{
@@ -229,6 +241,7 @@ mod test {
(i64::MAX, &[254, 255, 255, 255, 255, 255, 255, 255, 255, 1]),
];
for &(n, bytes) in CASES {
+ #[cfg(feature = "std")]
println!("testing {}", n);
let int = Int(n);
let got_bytes = to_vec(&int).unwrap();
@@ -247,6 +260,7 @@ mod test {
(u64::MAX, &[255, 255, 255, 255, 255, 255, 255, 255, 255, 1]),
];
for &(n, bytes) in CASES {
+ #[cfg(feature = "std")]
println!("testing {}", n);
let int = Uint(n);
let got_bytes = to_vec(&int).unwrap();
diff --git a/src/ser.rs b/src/ser.rs
index cf385a0..f920f87 100644
--- a/src/ser.rs
+++ b/src/ser.rs
@@ -1,6 +1,9 @@
use crate::{error::Error, Uint};
use serde::{ser, Serialize};
-use std::io::Write;
+use crate::compat::{
+ io::Write,
+ vec::Vec
+};
pub struct Serializer<W> {
writer: W,
@@ -419,6 +422,7 @@ where
mod test {
#[test]
fn test_unbounded_sequence() {
+ use crate::compat::vec::Vec;
use serde::Serializer;
let seq = [1, 2, 3];
let vec = Vec::<u8>::new();
--
2.30.1 (Apple Git-130)