Skip to content
This repository has been archived by the owner on Jul 2, 2024. It is now read-only.

Add no-std support #1

Merged
merged 1 commit into from
Feb 27, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 5 additions & 2 deletions .github/workflows/rust.yml
Original file line number Diff line number Diff line change
Expand Up @@ -28,5 +28,8 @@ jobs:
- name: Set up Rust
uses: actions-rust-lang/setup-rust-toolchain@v1

- name: Run tests
run: cargo test --all-features
- name: Run tests (std)
run: cargo test

- name: Run tests (no_std)
run: cargo test --no-default-features --features alloc
5 changes: 5 additions & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -11,3 +11,8 @@ ryu = "1.0"

[dev-dependencies]
serde = { version = "1.0", features = ["derive"] }

[features]
default = ["std"]
std = ["serde/std"]
alloc = ["serde/alloc"]
3 changes: 2 additions & 1 deletion src/de.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
use alloc::vec::Vec;
use core::str;
use std::str::FromStr;
use core::str::FromStr;

use serde::de;
use serde::de::{DeserializeSeed, Unexpected, Visitor};
Expand Down
4 changes: 3 additions & 1 deletion src/error.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
use alloc::boxed::Box;
use alloc::string::ToString;
use core::fmt;
use core::result;
use std::fmt;

pub type Result<T> = result::Result<T, Error>;

Expand Down
81 changes: 81 additions & 0 deletions src/io/core.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,81 @@
//! Copy from [serde-rs/json](https://github.com/serde-rs/json/blob/207a57b68880769c81d525f9f5b38d3be1340806/src/io/core.rs)

//! Reimplements core logic and types from `std::io` in an `alloc`-friendly
//! fashion.

use alloc::vec::Vec;
use core::fmt::{self, Display};
use core::result;

pub enum ErrorKind {
Other,
}

// I/O errors can never occur in no-std mode. All our no-std I/O implementations
// are infallible.
pub struct Error;

impl Display for Error {
fn fmt(&self, _formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
unreachable!()
}
}

impl Error {
pub(crate) fn new(_kind: ErrorKind, _error: &'static str) -> Error {
Error
}
}

pub type Result<T> = result::Result<T, Error>;

pub trait Write {
fn write(&mut self, buf: &[u8]) -> Result<usize>;

fn write_all(&mut self, buf: &[u8]) -> Result<()> {
// All our Write impls in no_std mode always write the whole buffer in
// one call infallibly.
let result = self.write(buf);
debug_assert!(result.is_ok());
debug_assert_eq!(result.unwrap_or(0), buf.len());
Ok(())
}

fn flush(&mut self) -> Result<()>;
}

impl<W: Write> Write for &mut W {
#[inline]
fn write(&mut self, buf: &[u8]) -> Result<usize> {
(*self).write(buf)
}

#[inline]
fn write_all(&mut self, buf: &[u8]) -> Result<()> {
(*self).write_all(buf)
}

#[inline]
fn flush(&mut self) -> Result<()> {
(*self).flush()
}
}

impl Write for Vec<u8> {
#[inline]
fn write(&mut self, buf: &[u8]) -> Result<usize> {
self.extend_from_slice(buf);
Ok(buf.len())
}

#[inline]
fn write_all(&mut self, buf: &[u8]) -> Result<()> {
self.extend_from_slice(buf);
Ok(())
}

#[inline]
fn flush(&mut self) -> Result<()> {
Ok(())
}
}
19 changes: 19 additions & 0 deletions src/io/mod.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
//! Copy from [serde-rs/json](https://github.com/serde-rs/json/blob/0de7b516f504b5c1df1774425eef18efb132ed93/src/io/mod.rs)

//! A tiny, `no_std`-friendly facade around `std::io`.
//! Reexports types from `std` when available; otherwise reimplements and
//! provides some of the core logic.
//!
//! The main reason that `std::io` hasn't found itself reexported as part of
//! the `core` crate is the `std::io::{Read, Write}` traits' reliance on
//! `std::io::Error`, which may contain internally a heap-allocated `Box<Error>`
//! and/or now relying on OS-specific `std::backtrace::Backtrace`.

pub use self::imp::{Result, Write};

#[cfg(not(feature = "std"))]
#[path = "core.rs"]
mod imp;

#[cfg(feature = "std")]
use std::io as imp;
14 changes: 10 additions & 4 deletions src/lib.rs
Original file line number Diff line number Diff line change
@@ -1,8 +1,14 @@
#![allow(unused)]
#![cfg_attr(not(feature = "std"), no_std)]

extern crate alloc;

pub use crate::de::{Deserializer, from_slice, from_str};
pub use crate::error::{Error, Result};
pub use crate::ser::{Serializer, to_string, to_vec, to_writer};

mod de;
mod error;
mod read;
mod ser;

pub use crate::de::{from_slice, from_str, Deserializer};
pub use crate::error::{Error, Result};
pub use crate::ser::{to_string, to_vec, to_writer, Serializer};
mod io;
Loading