Skip to content

Commit

Permalink
Merge pull request #7 from jelacious/no_std_ipaddr
Browse files Browse the repository at this point in the history
`no_std` support
  • Loading branch information
yescallop committed Mar 11, 2023
2 parents f0a0536 + 86e15b6 commit dcaceba
Show file tree
Hide file tree
Showing 10 changed files with 99 additions and 58 deletions.
4 changes: 2 additions & 2 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ jobs:
profile: minimal
toolchain: nightly
override: true
- name: Test with no feature
- name: Test with default features
uses: actions-rs/cargo@v1
with:
command: test
Expand All @@ -28,7 +28,7 @@ jobs:
uses: actions-rs/cargo@v1
with:
command: doc
args: --no-deps --features ipv_future,rfc6874bis
args: --no-deps --features ipv_future,rfc6874bis,std
- name: Deploy docs
uses: peaceiris/actions-gh-pages@v3
with:
Expand Down
4 changes: 3 additions & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -15,12 +15,14 @@ categories = ["encoding", "parser-implementations"]
bitflags = "1.3.2"

[features]
default = ["std"]
ipv_future = []
rfc6874bis = []
unstable = []
std = []

[package.metadata.docs.rs]
features = ["ipv_future", "rfc6874bis"]
features = ["ipv_future", "rfc6874bis", "std"]

# Commented out to reduce compile time.

Expand Down
8 changes: 6 additions & 2 deletions src/enc/estring.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,8 @@
use std::{borrow::Borrow, fmt, hash, marker::PhantomData, ops::Deref};
use alloc::string::String;
use core::{borrow::Borrow, fmt, hash, marker::PhantomData, ops::Deref};

#[cfg(feature = "unstable")]
use alloc::vec::Vec;

use super::{
encoder::Encoder,
Expand Down Expand Up @@ -341,7 +345,7 @@ impl<E: Encoder> Clone for EString<E> {
impl<E: Encoder> fmt::Debug for EString<E> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.debug_struct("EString")
.field("encoder", &std::any::type_name::<E>())
.field("encoder", &core::any::type_name::<E>())
.field("contents", &self.string)
.finish()
}
Expand Down
8 changes: 5 additions & 3 deletions src/enc/imp.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,11 @@ use super::table;
#[cfg(feature = "unstable")]
use super::table::Table;

use std::{fmt, ptr};
use alloc::vec::Vec;
use core::{fmt, ptr};

#[cfg(feature = "unstable")]
use std::{borrow::Cow, str};
use alloc::{borrow::Cow, str, string::String};

/// Returns immediately with an encoding error.
macro_rules! err {
Expand Down Expand Up @@ -57,6 +58,7 @@ impl EncodingError {
}
}

#[cfg(feature = "std")]
impl std::error::Error for EncodingError {}

impl fmt::Display for EncodingError {
Expand All @@ -70,7 +72,7 @@ impl fmt::Display for EncodingError {
}
}

pub(crate) type Result<T, E = EncodingError> = std::result::Result<T, E>;
pub(crate) type Result<T, E = EncodingError> = core::result::Result<T, E>;

#[cfg(feature = "unstable")]
const fn gen_hex_table() -> [u8; 512] {
Expand Down
14 changes: 9 additions & 5 deletions src/enc/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -89,13 +89,16 @@ pub fn validate<S: AsRef<[u8]> + ?Sized>(s: &S, table: &Table) -> Result<()> {
}
}

use std::{
use alloc::{
borrow::{self, Cow},
string::{FromUtf8Error, String},
vec::Vec,
};
use core::{
fmt, hash,
iter::FusedIterator,
mem,
str::{self, Utf8Error},
string::FromUtf8Error,
};

use crate::view::View;
Expand Down Expand Up @@ -275,7 +278,7 @@ impl EStr {
/// assert_eq!(dec.to_str()?, "233");
/// assert!(dec.decoded_any());
/// assert_eq!(buf, b"233");
/// # Ok::<_, std::str::Utf8Error>(())
/// # Ok::<_, core::str::Utf8Error>(())
/// ```
#[cfg(feature = "unstable")]
#[inline]
Expand Down Expand Up @@ -778,7 +781,7 @@ impl FusedIterator for SplitView<'_> {}
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
pub struct BufferTooSmallError(());

#[cfg(feature = "unstable")]
#[cfg(all(feature = "unstable", feature = "std"))]
impl std::error::Error for BufferTooSmallError {}

#[cfg(feature = "unstable")]
Expand All @@ -791,7 +794,8 @@ impl fmt::Display for BufferTooSmallError {
#[cfg(feature = "unstable")]
pub(crate) mod internal {
use crate::enc::BufferTooSmallError;
use std::{collections::TryReserveError, mem::MaybeUninit};
use alloc::{collections::TryReserveError, string::String, vec::Vec};
use core::mem::MaybeUninit;

pub trait AsMutVec {
unsafe fn as_mut_vec(&mut self) -> &mut Vec<u8>;
Expand Down
3 changes: 2 additions & 1 deletion src/fmt.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
use super::*;
use std::fmt;
use alloc::string::String;
use core::fmt;

impl fmt::Display for ParseError {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
Expand Down
10 changes: 8 additions & 2 deletions src/internal.rs
Original file line number Diff line number Diff line change
@@ -1,12 +1,16 @@
#![allow(missing_debug_implementations)]

use std::{
use alloc::{string::String, vec::Vec};
use core::{
cell::Cell,
mem::MaybeUninit,
num::NonZeroU32,
ops::{Deref, DerefMut},
};

#[cfg(feature = "std")]
use std::net::{Ipv4Addr, Ipv6Addr};

use super::*;
use bitflags::bitflags;

Expand Down Expand Up @@ -231,15 +235,17 @@ pub struct AuthData {

#[derive(Clone, Copy)]
pub union RawHostData {
#[cfg(feature = "std")]
pub ipv4_addr: Ipv4Addr,
pub ipv6: Ipv6Data,
#[cfg(feature = "ipv_future")]
pub ipv_future_dot_i: u32,
pub reg_name: (),
pub none: (),
}

#[derive(Clone, Copy)]
pub struct Ipv6Data {
#[cfg(feature = "std")]
pub addr: Ipv6Addr,
#[cfg(feature = "rfc6874bis")]
pub zone_id_start: Option<NonZeroU32>,
Expand Down
49 changes: 31 additions & 18 deletions src/lib.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
#![warn(missing_debug_implementations, missing_docs, rust_2018_idioms)]
#![deny(unsafe_op_in_unsafe_fn)]
#![cfg_attr(not(feature = "std"), no_std)]

//! A generic URI parser that strictly adheres to IETF [RFC 3986].
//!
Expand All @@ -9,11 +10,14 @@
//!
//! # Feature flags
//!
//! All features are disabled by default. However, note that these features each
//! alter the enum [`HostData`] in a backward incompatible way that could make it
//! All features except `std` are disabled by default. Note that the last two features
//! each alter the enum [`HostData`] in a backward incompatible way that could make it
//! impossible for two crates that depend on different features of `fluent-uri` to
//! be used together.
//!
//! - `std`: Enables `std` support. This includes [`Error`] implementations
//! and `Ip{v4, v6}Addr` support in [`HostData`].
//!
//! - `ipv_future`: Enables the parsing of [IPvFuture] literal addresses,
//! which fails with [`InvalidIpLiteral`] when disabled.
//!
Expand All @@ -26,9 +30,12 @@
//!
//! This feature is based on the homonymous [draft] and is thus subject to change.
//!
//! [`Error`]: std::error::Error
//! [IPvFuture]: https://datatracker.ietf.org/doc/html/rfc3986/#section-3.2.2
//! [`InvalidIpLiteral`]: ParseErrorKind::InvalidIpLiteral
//! [draft]: https://datatracker.ietf.org/doc/html/draft-ietf-6man-rfc6874bis-02
//! [draft]: https://datatracker.ietf.org/doc/html/draft-ietf-6man-rfc6874bis-05

extern crate alloc;

/// Utilities for percent-encoding.
pub mod enc;
Expand All @@ -41,13 +48,11 @@ pub use view::*;
mod parser;

use crate::enc::{EStr, Split};
use std::{
marker::PhantomData,
mem::ManuallyDrop,
net::{Ipv4Addr, Ipv6Addr},
ptr::NonNull,
slice, str,
};
use alloc::{string::String, vec::Vec};
use core::{iter::Iterator, marker::PhantomData, mem::ManuallyDrop, ptr::NonNull, slice, str};

#[cfg(feature = "std")]
use std::net::{Ipv4Addr, Ipv6Addr};

mod internal;
use internal::*;
Expand Down Expand Up @@ -90,9 +95,10 @@ impl ParseError {
}
}

#[cfg(feature = "std")]
impl std::error::Error for ParseError {}

type Result<T, E = ParseError> = std::result::Result<T, E>;
type Result<T, E = ParseError> = core::result::Result<T, E>;

#[cold]
fn len_overflow() -> ! {
Expand Down Expand Up @@ -135,7 +141,7 @@ fn len_overflow() -> ! {
/// # Examples
///
/// Create and convert between `Uri<&str>` and `Uri<String>`:
///
///
/// ```
/// use fluent_uri::Uri;
///
Expand Down Expand Up @@ -882,19 +888,22 @@ impl<'i, 'o, T: Io<'i, 'o>> Host<T> {
/// Returns the structured host data.
#[inline]
pub fn data(&'i self) -> HostData<'o> {
let data = self.raw_data();
let _data = self.raw_data();
let tag = self.auth.uri.tag;
// SAFETY: We only access the union after checking the tag.
unsafe {
if tag.contains(Tag::HOST_REG_NAME) {
// SAFETY: The validation is done.
return HostData::RegName(EStr::new_unchecked(self.as_str().as_bytes()));
} else if tag.contains(Tag::HOST_IPV4) {
return HostData::Ipv4(data.ipv4_addr);
return HostData::Ipv4(
#[cfg(feature = "std")]
_data.ipv4_addr,
);
}
#[cfg(feature = "ipv_future")]
if !tag.contains(Tag::HOST_IPV6) {
let dot_i = data.ipv_future_dot_i;
let dot_i = _data.ipv_future_dot_i;
let bounds = self.bounds();
// SAFETY: The indexes are within bounds and the validation is done.
return HostData::IpvFuture {
Expand All @@ -903,10 +912,11 @@ impl<'i, 'o, T: Io<'i, 'o>> Host<T> {
};
}
HostData::Ipv6 {
addr: data.ipv6.addr,
#[cfg(feature = "std")]
addr: _data.ipv6.addr,
// SAFETY: The indexes are within bounds and the validation is done.
#[cfg(feature = "rfc6874bis")]
zone_id: data
zone_id: _data
.ipv6
.zone_id_start
.map(|start| self.auth.uri.slice(start.get(), self.bounds().1 - 1)),
Expand All @@ -919,10 +929,13 @@ impl<'i, 'o, T: Io<'i, 'o>> Host<T> {
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum HostData<'a> {
/// An IPv4 address.
Ipv4(Ipv4Addr),
#[cfg_attr(not(feature = "std"), non_exhaustive)]
Ipv4(#[cfg(feature = "std")] Ipv4Addr),
/// An IPv6 address.
#[cfg_attr(not(feature = "std"), non_exhaustive)]
Ipv6 {
/// The address.
#[cfg(feature = "std")]
addr: Ipv6Addr,
/// An optional zone identifier.
///
Expand Down

0 comments on commit dcaceba

Please sign in to comment.