Merge pull request #715 from serde-rs/nostd
Support serde_derive on no_std
This commit is contained in:
commit
b9d865d8e7
@ -18,6 +18,7 @@ script:
|
|||||||
- (cd testing && travis-cargo --skip nightly test)
|
- (cd testing && travis-cargo --skip nightly test)
|
||||||
- (cd testing && travis-cargo --only nightly test -- --features unstable-testing)
|
- (cd testing && travis-cargo --only nightly test -- --features unstable-testing)
|
||||||
- (cd serde_derive && travis-cargo --only nightly test)
|
- (cd serde_derive && travis-cargo --only nightly test)
|
||||||
|
- (cd serde_derive/no-std-tests && travis-cargo --only nightly build)
|
||||||
#- (cd examples/serde-syntex-example && travis-cargo --skip nightly run)
|
#- (cd examples/serde-syntex-example && travis-cargo --skip nightly run)
|
||||||
#- (cd examples/serde-syntex-example && travis-cargo --only nightly run -- --no-default-features --features unstable)
|
#- (cd examples/serde-syntex-example && travis-cargo --only nightly run -- --no-default-features --features unstable)
|
||||||
- (cd serde && travis-cargo --only stable doc)
|
- (cd serde && travis-cargo --only stable doc)
|
||||||
|
33
serde/src/export.rs
Normal file
33
serde/src/export.rs
Normal file
@ -0,0 +1,33 @@
|
|||||||
|
#[cfg(all(feature = "collections", not(feature = "std")))]
|
||||||
|
use collections::String;
|
||||||
|
|
||||||
|
#[cfg(feature = "std")]
|
||||||
|
use std::borrow::Cow;
|
||||||
|
#[cfg(all(feature = "collections", not(feature = "std")))]
|
||||||
|
use collections::borrow::Cow;
|
||||||
|
|
||||||
|
pub use core::default::Default;
|
||||||
|
pub use core::fmt;
|
||||||
|
pub use core::marker::PhantomData;
|
||||||
|
pub use core::result::Result;
|
||||||
|
|
||||||
|
#[cfg(any(feature = "collections", feature = "std"))]
|
||||||
|
pub fn from_utf8_lossy(bytes: &[u8]) -> Cow<str> {
|
||||||
|
String::from_utf8_lossy(bytes)
|
||||||
|
}
|
||||||
|
|
||||||
|
// The generated code calls this like:
|
||||||
|
//
|
||||||
|
// let value = &_serde::export::from_utf8_lossy(bytes);
|
||||||
|
// Err(_serde::de::Error::unknown_variant(value, VARIANTS))
|
||||||
|
//
|
||||||
|
// so it is okay for the return type to be different from the std case as long
|
||||||
|
// as the above works.
|
||||||
|
#[cfg(not(any(feature = "collections", feature = "std")))]
|
||||||
|
pub fn from_utf8_lossy(bytes: &[u8]) -> &str {
|
||||||
|
use core::str;
|
||||||
|
// Three unicode replacement characters if it fails. They look like a
|
||||||
|
// white-on-black question mark. The user will recognize it as invalid
|
||||||
|
// UTF-8.
|
||||||
|
str::from_utf8(bytes).unwrap_or("\u{fffd}\u{fffd}\u{fffd}")
|
||||||
|
}
|
@ -31,7 +31,7 @@ extern crate core as actual_core;
|
|||||||
#[cfg(feature = "std")]
|
#[cfg(feature = "std")]
|
||||||
mod core {
|
mod core {
|
||||||
pub use std::{ops, hash, fmt, cmp, marker, mem, i8, i16, i32, i64, u8, u16, u32, u64, isize,
|
pub use std::{ops, hash, fmt, cmp, marker, mem, i8, i16, i32, i64, u8, u16, u32, u64, isize,
|
||||||
usize, f32, f64, char, str, num, slice, iter, cell};
|
usize, f32, f64, char, str, num, slice, iter, cell, default, result};
|
||||||
#[cfg(feature = "unstable")]
|
#[cfg(feature = "unstable")]
|
||||||
pub use actual_core::nonzero;
|
pub use actual_core::nonzero;
|
||||||
}
|
}
|
||||||
@ -50,3 +50,7 @@ pub mod ser;
|
|||||||
#[cfg_attr(feature = "std", doc(hidden))]
|
#[cfg_attr(feature = "std", doc(hidden))]
|
||||||
pub mod error;
|
pub mod error;
|
||||||
mod utils;
|
mod utils;
|
||||||
|
|
||||||
|
// Generated code uses these to support no_std. Not public API.
|
||||||
|
#[doc(hidden)]
|
||||||
|
pub mod export;
|
||||||
|
@ -36,7 +36,7 @@ pub fn expand_derive_deserialize(item: &syn::MacroInput) -> Result<Tokens, Strin
|
|||||||
extern crate serde as _serde;
|
extern crate serde as _serde;
|
||||||
#[automatically_derived]
|
#[automatically_derived]
|
||||||
impl #impl_generics _serde::Deserialize for #ty #where_clause {
|
impl #impl_generics _serde::Deserialize for #ty #where_clause {
|
||||||
fn deserialize<__D>(deserializer: __D) -> ::std::result::Result<#ty, __D::Error>
|
fn deserialize<__D>(deserializer: __D) -> _serde::export::Result<#ty, __D::Error>
|
||||||
where __D: _serde::Deserializer
|
where __D: _serde::Deserializer
|
||||||
#body
|
#body
|
||||||
}
|
}
|
||||||
@ -158,11 +158,11 @@ fn deserialize_visitor(generics: &syn::Generics) -> (Tokens, Tokens, Tokens) {
|
|||||||
let phantom_types = generics.lifetimes.iter()
|
let phantom_types = generics.lifetimes.iter()
|
||||||
.map(|lifetime_def| {
|
.map(|lifetime_def| {
|
||||||
let lifetime = &lifetime_def.lifetime;
|
let lifetime = &lifetime_def.lifetime;
|
||||||
quote!(::std::marker::PhantomData<& #lifetime ()>)
|
quote!(_serde::export::PhantomData<& #lifetime ()>)
|
||||||
}).chain(generics.ty_params.iter()
|
}).chain(generics.ty_params.iter()
|
||||||
.map(|ty_param| {
|
.map(|ty_param| {
|
||||||
let ident = &ty_param.ident;
|
let ident = &ty_param.ident;
|
||||||
quote!(::std::marker::PhantomData<#ident>)
|
quote!(_serde::export::PhantomData<#ident>)
|
||||||
}));
|
}));
|
||||||
|
|
||||||
let all_params = generics.lifetimes.iter()
|
let all_params = generics.lifetimes.iter()
|
||||||
@ -182,7 +182,7 @@ fn deserialize_visitor(generics: &syn::Generics) -> (Tokens, Tokens, Tokens) {
|
|||||||
Some(quote!(::<#(#ty_param_idents),*>))
|
Some(quote!(::<#(#ty_param_idents),*>))
|
||||||
};
|
};
|
||||||
|
|
||||||
let phantom_exprs = iter::repeat(quote!(::std::marker::PhantomData)).take(num_phantoms);
|
let phantom_exprs = iter::repeat(quote!(_serde::export::PhantomData)).take(num_phantoms);
|
||||||
|
|
||||||
(
|
(
|
||||||
quote! {
|
quote! {
|
||||||
@ -208,19 +208,19 @@ fn deserialize_unit_struct(
|
|||||||
impl _serde::de::Visitor for __Visitor {
|
impl _serde::de::Visitor for __Visitor {
|
||||||
type Value = #type_ident;
|
type Value = #type_ident;
|
||||||
|
|
||||||
fn expecting(&self, formatter: &mut ::std::fmt::Formatter) -> ::std::fmt::Result {
|
fn expecting(&self, formatter: &mut _serde::export::fmt::Formatter) -> _serde::export::fmt::Result {
|
||||||
formatter.write_str(#expecting)
|
formatter.write_str(#expecting)
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
fn visit_unit<__E>(self) -> ::std::result::Result<#type_ident, __E>
|
fn visit_unit<__E>(self) -> _serde::export::Result<#type_ident, __E>
|
||||||
where __E: _serde::de::Error,
|
where __E: _serde::de::Error,
|
||||||
{
|
{
|
||||||
Ok(#type_ident)
|
Ok(#type_ident)
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
fn visit_seq<__V>(self, _: __V) -> ::std::result::Result<#type_ident, __V::Error>
|
fn visit_seq<__V>(self, _: __V) -> _serde::export::Result<#type_ident, __V::Error>
|
||||||
where __V: _serde::de::SeqVisitor,
|
where __V: _serde::de::SeqVisitor,
|
||||||
{
|
{
|
||||||
Ok(#type_ident)
|
Ok(#type_ident)
|
||||||
@ -297,14 +297,14 @@ fn deserialize_tuple(
|
|||||||
impl #impl_generics _serde::de::Visitor for #visitor_ty #where_clause {
|
impl #impl_generics _serde::de::Visitor for #visitor_ty #where_clause {
|
||||||
type Value = #ty;
|
type Value = #ty;
|
||||||
|
|
||||||
fn expecting(&self, formatter: &mut ::std::fmt::Formatter) -> ::std::fmt::Result {
|
fn expecting(&self, formatter: &mut _serde::export::fmt::Formatter) -> _serde::export::fmt::Result {
|
||||||
formatter.write_str(#expecting)
|
formatter.write_str(#expecting)
|
||||||
}
|
}
|
||||||
|
|
||||||
#visit_newtype_struct
|
#visit_newtype_struct
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
fn visit_seq<__V>(self, #visitor_var: __V) -> ::std::result::Result<#ty, __V::Error>
|
fn visit_seq<__V>(self, #visitor_var: __V) -> _serde::export::Result<#ty, __V::Error>
|
||||||
where __V: _serde::de::SeqVisitor
|
where __V: _serde::de::SeqVisitor
|
||||||
{
|
{
|
||||||
#visit_seq
|
#visit_seq
|
||||||
@ -408,7 +408,7 @@ fn deserialize_newtype_struct(
|
|||||||
};
|
};
|
||||||
quote! {
|
quote! {
|
||||||
#[inline]
|
#[inline]
|
||||||
fn visit_newtype_struct<__E>(self, __e: __E) -> ::std::result::Result<Self::Value, __E::Error>
|
fn visit_newtype_struct<__E>(self, __e: __E) -> _serde::export::Result<Self::Value, __E::Error>
|
||||||
where __E: _serde::Deserializer,
|
where __E: _serde::Deserializer,
|
||||||
{
|
{
|
||||||
Ok(#type_path(#value))
|
Ok(#type_path(#value))
|
||||||
@ -480,19 +480,19 @@ fn deserialize_struct(
|
|||||||
impl #impl_generics _serde::de::Visitor for #visitor_ty #where_clause {
|
impl #impl_generics _serde::de::Visitor for #visitor_ty #where_clause {
|
||||||
type Value = #ty;
|
type Value = #ty;
|
||||||
|
|
||||||
fn expecting(&self, formatter: &mut ::std::fmt::Formatter) -> ::std::fmt::Result {
|
fn expecting(&self, formatter: &mut _serde::export::fmt::Formatter) -> _serde::export::fmt::Result {
|
||||||
formatter.write_str(#expecting)
|
formatter.write_str(#expecting)
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
fn visit_seq<__V>(self, #visitor_var: __V) -> ::std::result::Result<#ty, __V::Error>
|
fn visit_seq<__V>(self, #visitor_var: __V) -> _serde::export::Result<#ty, __V::Error>
|
||||||
where __V: _serde::de::SeqVisitor
|
where __V: _serde::de::SeqVisitor
|
||||||
{
|
{
|
||||||
#visit_seq
|
#visit_seq
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
fn visit_map<__V>(self, mut visitor: __V) -> ::std::result::Result<#ty, __V::Error>
|
fn visit_map<__V>(self, mut visitor: __V) -> _serde::export::Result<#ty, __V::Error>
|
||||||
where __V: _serde::de::MapVisitor
|
where __V: _serde::de::MapVisitor
|
||||||
{
|
{
|
||||||
#visit_map
|
#visit_map
|
||||||
@ -585,11 +585,11 @@ fn deserialize_item_enum(
|
|||||||
impl #impl_generics _serde::de::Visitor for #visitor_ty #where_clause {
|
impl #impl_generics _serde::de::Visitor for #visitor_ty #where_clause {
|
||||||
type Value = #ty;
|
type Value = #ty;
|
||||||
|
|
||||||
fn expecting(&self, formatter: &mut ::std::fmt::Formatter) -> ::std::fmt::Result {
|
fn expecting(&self, formatter: &mut _serde::export::fmt::Formatter) -> _serde::export::fmt::Result {
|
||||||
formatter.write_str(#expecting)
|
formatter.write_str(#expecting)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn visit_enum<__V>(self, visitor: __V) -> ::std::result::Result<#ty, __V::Error>
|
fn visit_enum<__V>(self, visitor: __V) -> _serde::export::Result<#ty, __V::Error>
|
||||||
where __V: _serde::de::EnumVisitor,
|
where __V: _serde::de::EnumVisitor,
|
||||||
{
|
{
|
||||||
#match_variant
|
#match_variant
|
||||||
@ -696,7 +696,7 @@ fn deserialize_field_visitor(
|
|||||||
let variant_indices = 0usize..;
|
let variant_indices = 0usize..;
|
||||||
let fallthrough_msg = format!("variant index 0 <= i < {}", fields.len());
|
let fallthrough_msg = format!("variant index 0 <= i < {}", fields.len());
|
||||||
Some(quote! {
|
Some(quote! {
|
||||||
fn visit_usize<__E>(self, value: usize) -> ::std::result::Result<__Field, __E>
|
fn visit_usize<__E>(self, value: usize) -> _serde::export::Result<__Field, __E>
|
||||||
where __E: _serde::de::Error
|
where __E: _serde::de::Error
|
||||||
{
|
{
|
||||||
match value {
|
match value {
|
||||||
@ -731,7 +731,7 @@ fn deserialize_field_visitor(
|
|||||||
Some(quote! {
|
Some(quote! {
|
||||||
// TODO https://github.com/serde-rs/serde/issues/666
|
// TODO https://github.com/serde-rs/serde/issues/666
|
||||||
// update this to use str::from_utf8(value).unwrap_or("<22><><EFBFBD>") on no_std
|
// update this to use str::from_utf8(value).unwrap_or("<22><><EFBFBD>") on no_std
|
||||||
let value = &::std::string::String::from_utf8_lossy(value);
|
let value = &_serde::export::from_utf8_lossy(value);
|
||||||
})
|
})
|
||||||
} else {
|
} else {
|
||||||
None
|
None
|
||||||
@ -746,7 +746,7 @@ fn deserialize_field_visitor(
|
|||||||
|
|
||||||
impl _serde::Deserialize for __Field {
|
impl _serde::Deserialize for __Field {
|
||||||
#[inline]
|
#[inline]
|
||||||
fn deserialize<__D>(deserializer: __D) -> ::std::result::Result<__Field, __D::Error>
|
fn deserialize<__D>(deserializer: __D) -> _serde::export::Result<__Field, __D::Error>
|
||||||
where __D: _serde::Deserializer,
|
where __D: _serde::Deserializer,
|
||||||
{
|
{
|
||||||
struct __FieldVisitor;
|
struct __FieldVisitor;
|
||||||
@ -754,13 +754,13 @@ fn deserialize_field_visitor(
|
|||||||
impl _serde::de::Visitor for __FieldVisitor {
|
impl _serde::de::Visitor for __FieldVisitor {
|
||||||
type Value = __Field;
|
type Value = __Field;
|
||||||
|
|
||||||
fn expecting(&self, formatter: &mut ::std::fmt::Formatter) -> ::std::fmt::Result {
|
fn expecting(&self, formatter: &mut _serde::export::fmt::Formatter) -> _serde::export::fmt::Result {
|
||||||
formatter.write_str("field name")
|
formatter.write_str("field name")
|
||||||
}
|
}
|
||||||
|
|
||||||
#visit_usize
|
#visit_usize
|
||||||
|
|
||||||
fn visit_str<__E>(self, value: &str) -> ::std::result::Result<__Field, __E>
|
fn visit_str<__E>(self, value: &str) -> _serde::export::Result<__Field, __E>
|
||||||
where __E: _serde::de::Error
|
where __E: _serde::de::Error
|
||||||
{
|
{
|
||||||
match value {
|
match value {
|
||||||
@ -771,7 +771,7 @@ fn deserialize_field_visitor(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn visit_bytes<__E>(self, value: &[u8]) -> ::std::result::Result<__Field, __E>
|
fn visit_bytes<__E>(self, value: &[u8]) -> _serde::export::Result<__Field, __E>
|
||||||
where __E: _serde::de::Error
|
where __E: _serde::de::Error
|
||||||
{
|
{
|
||||||
match value {
|
match value {
|
||||||
@ -981,18 +981,18 @@ fn wrap_deserialize_with(
|
|||||||
quote! {
|
quote! {
|
||||||
struct __SerdeDeserializeWithStruct #impl_generics #where_clause {
|
struct __SerdeDeserializeWithStruct #impl_generics #where_clause {
|
||||||
value: #field_ty,
|
value: #field_ty,
|
||||||
phantom: ::std::marker::PhantomData<#phantom_ty>,
|
phantom: _serde::export::PhantomData<#phantom_ty>,
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
quote! {
|
quote! {
|
||||||
impl #impl_generics _serde::Deserialize for #wrapper_ty #where_clause {
|
impl #impl_generics _serde::Deserialize for #wrapper_ty #where_clause {
|
||||||
fn deserialize<__D>(__d: __D) -> ::std::result::Result<Self, __D::Error>
|
fn deserialize<__D>(__d: __D) -> _serde::export::Result<Self, __D::Error>
|
||||||
where __D: _serde::Deserializer
|
where __D: _serde::Deserializer
|
||||||
{
|
{
|
||||||
let value = try!(#deserialize_with(__d));
|
let value = try!(#deserialize_with(__d));
|
||||||
Ok(__SerdeDeserializeWithStruct {
|
Ok(__SerdeDeserializeWithStruct {
|
||||||
value: value,
|
value: value,
|
||||||
phantom: ::std::marker::PhantomData,
|
phantom: _serde::export::PhantomData,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1004,7 +1004,7 @@ fn wrap_deserialize_with(
|
|||||||
fn expr_is_missing(attrs: &attr::Field) -> Tokens {
|
fn expr_is_missing(attrs: &attr::Field) -> Tokens {
|
||||||
match *attrs.default() {
|
match *attrs.default() {
|
||||||
attr::FieldDefault::Default => {
|
attr::FieldDefault::Default => {
|
||||||
return quote!(::std::default::Default::default());
|
return quote!(_serde::export::Default::default());
|
||||||
}
|
}
|
||||||
attr::FieldDefault::Path(ref path) => {
|
attr::FieldDefault::Path(ref path) => {
|
||||||
return quote!(#path());
|
return quote!(#path());
|
||||||
|
@ -30,7 +30,7 @@ pub fn expand_derive_serialize(item: &syn::MacroInput) -> Result<Tokens, String>
|
|||||||
extern crate serde as _serde;
|
extern crate serde as _serde;
|
||||||
#[automatically_derived]
|
#[automatically_derived]
|
||||||
impl #impl_generics _serde::Serialize for #ty #where_clause {
|
impl #impl_generics _serde::Serialize for #ty #where_clause {
|
||||||
fn serialize<__S>(&self, _serializer: __S) -> ::std::result::Result<__S::Ok, __S::Error>
|
fn serialize<__S>(&self, _serializer: __S) -> _serde::export::Result<__S::Ok, __S::Error>
|
||||||
where __S: _serde::Serializer
|
where __S: _serde::Serializer
|
||||||
{
|
{
|
||||||
#body
|
#body
|
||||||
@ -541,7 +541,7 @@ fn wrap_serialize_with(
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl #wrapper_generics _serde::Serialize for #wrapper_ty #where_clause {
|
impl #wrapper_generics _serde::Serialize for #wrapper_ty #where_clause {
|
||||||
fn serialize<__S>(&self, __s: __S) -> ::std::result::Result<__S::Ok, __S::Error>
|
fn serialize<__S>(&self, __s: __S) -> _serde::export::Result<__S::Ok, __S::Error>
|
||||||
where __S: _serde::Serializer
|
where __S: _serde::Serializer
|
||||||
{
|
{
|
||||||
#path(self.value, __s)
|
#path(self.value, __s)
|
||||||
|
8
serde_derive/no-std-tests/Cargo.toml
Normal file
8
serde_derive/no-std-tests/Cargo.toml
Normal file
@ -0,0 +1,8 @@
|
|||||||
|
[package]
|
||||||
|
name = "serde_derive_tests_no_std"
|
||||||
|
version = "0.9.0-rc2"
|
||||||
|
publish = false
|
||||||
|
|
||||||
|
[dependencies]
|
||||||
|
serde = { path = "../../serde", default-features = false }
|
||||||
|
serde_derive = { path = ".." }
|
50
serde_derive/no-std-tests/src/main.rs
Normal file
50
serde_derive/no-std-tests/src/main.rs
Normal file
@ -0,0 +1,50 @@
|
|||||||
|
#![feature(lang_items, start, libc)]
|
||||||
|
#![no_std]
|
||||||
|
|
||||||
|
extern crate libc;
|
||||||
|
|
||||||
|
#[start]
|
||||||
|
fn start(_argc: isize, _argv: *const *const u8) -> isize {
|
||||||
|
0
|
||||||
|
}
|
||||||
|
|
||||||
|
#[lang = "eh_personality"]
|
||||||
|
#[no_mangle]
|
||||||
|
pub extern fn rust_eh_personality() {}
|
||||||
|
|
||||||
|
#[lang = "eh_unwind_resume"]
|
||||||
|
#[no_mangle]
|
||||||
|
pub extern fn rust_eh_unwind_resume() {}
|
||||||
|
|
||||||
|
#[lang = "panic_fmt"]
|
||||||
|
#[no_mangle]
|
||||||
|
pub extern fn rust_begin_panic(_msg: core::fmt::Arguments,
|
||||||
|
_file: &'static str,
|
||||||
|
_line: u32) -> ! {
|
||||||
|
loop {}
|
||||||
|
}
|
||||||
|
|
||||||
|
//////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
#[macro_use]
|
||||||
|
extern crate serde_derive;
|
||||||
|
|
||||||
|
#[derive(Serialize, Deserialize)]
|
||||||
|
struct Unit;
|
||||||
|
|
||||||
|
#[derive(Serialize, Deserialize)]
|
||||||
|
struct Newtype(u8);
|
||||||
|
|
||||||
|
#[derive(Serialize, Deserialize)]
|
||||||
|
struct Tuple(u8, u8);
|
||||||
|
|
||||||
|
#[derive(Serialize, Deserialize)]
|
||||||
|
struct Struct { f: u8 }
|
||||||
|
|
||||||
|
#[derive(Serialize, Deserialize)]
|
||||||
|
enum Enum {
|
||||||
|
Unit,
|
||||||
|
Newtype(u8),
|
||||||
|
Tuple(u8, u8),
|
||||||
|
Struct { f: u8 },
|
||||||
|
}
|
Loading…
x
Reference in New Issue
Block a user