Repository: GREsau/schemars
Pull request #319 (2024-08-17 18:42:09)

Add `no_std` support via disabling the new default feature `std`
Implements #254 

Using schemars without std can be done by configuring it like this:
```toml
schemars = { version = "1.0.0-alpha.5", default-features = false, features = ["derive"] }
```
...where the `derive` feature can also be removed if you don't need to `derive(JsonSchema)`, of course.

Note that schemars always requires `alloc` - this cannot be disabled.


Patch:
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 84cdc1e..998deaa 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,5 +1,11 @@
 # Changelog
 
+## [1.0.0-alpha.5] - _in-dev_
+
+### Added
+
+- Schemars can now be used in `no_std` environments by disabling the new `std` feature flag (which is enabled by default). Schemars still requires an allocator to be available.
+
 ## [1.0.0-alpha.4] - 2024-08-17
 
 ### Fixed
diff --git a/Cargo.lock b/Cargo.lock
index 4833077..39e20b3 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -175,9 +175,9 @@ dependencies = [
 
 [[package]]
 name = "indexmap"
-version = "2.0.2"
+version = "2.4.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "8adf3ddd720272c6ea8bf59463c04e0f93d0bbf7c5439b691bca2987e0270897"
+checksum = "93ead53efc7ea8ed3cfb0c79fc8023fbb782a5432b52830b6518941cebe6505c"
 dependencies = [
  "equivalent",
  "hashbrown",
@@ -195,6 +195,12 @@ version = "0.2.8"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "4ec2a862134d2a7d32d7983ddcdd1c4923530833c9f2ea1a44fc5fa473989058"
 
+[[package]]
+name = "memchr"
+version = "2.5.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "2dffe52ecf27772e601905b7522cb4ef790d2cc203488bbd0e2fe85fcb74566d"
+
 [[package]]
 name = "num-bigint"
 version = "0.4.4"
@@ -346,18 +352,18 @@ checksum = "836fa6a3e1e547f9a2c4040802ec865b5d85f4014efe00555d7090a3dcaa1090"
 
 [[package]]
 name = "serde"
-version = "1.0.189"
+version = "1.0.208"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "8e422a44e74ad4001bdc8eede9a4570ab52f71190e9c076d14369f38b9200537"
+checksum = "cff085d2cb684faa248efb494c39b68e522822ac0de72ccf08109abde717cfb2"
 dependencies = [
  "serde_derive",
 ]
 
 [[package]]
 name = "serde_derive"
-version = "1.0.189"
+version = "1.0.208"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "1e48d1f918009ce3145511378cf68d613e3b3d9137d67272562080d68a2b32d5"
+checksum = "24008e81ff7613ed8e5ba0cfaf24e2c2f1e5b8a0495711e44fcd4882fca62bcf"
 dependencies = [
  "proc-macro2",
  "quote",
@@ -377,12 +383,13 @@ dependencies = [
 
 [[package]]
 name = "serde_json"
-version = "1.0.107"
+version = "1.0.125"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "6b420ce6e3d8bd882e9b243c6eed35dbc9a6110c9769e74b584e0d68d1f20c65"
+checksum = "83c8e735a073ccf5be70aa8066aa984eaf2fa000db6c8d0100ae605b366d31ed"
 dependencies = [
  "indexmap",
  "itoa",
+ "memchr",
  "ryu",
  "serde",
 ]
diff --git a/schemars/Cargo.toml b/schemars/Cargo.toml
index 74f26da..0c384a5 100644
--- a/schemars/Cargo.toml
+++ b/schemars/Cargo.toml
@@ -14,8 +14,8 @@ rust-version = "1.60"
 
 [dependencies]
 schemars_derive = { version = "=1.0.0-alpha.4", optional = true, path = "../schemars_derive" }
-serde = "1.0"
-serde_json = "1.0.25"
+serde = { version = "1.0", default-features = false, features = ["alloc"]}
+serde_json = { version =  "1.0.122", default-features = false, features = ["alloc"] }
 dyn-clone = "1.0"
 ref-cast = "1.0.22"
 
@@ -40,18 +40,37 @@ trybuild = "1.0"
 serde = { version = "1.0", features = ["derive"] }
 
 [features]
-default = ["derive"]
+default = ["derive", "std"]
 
+# Provide impls for common standard library types like `HashMap<K, V>`.
+# Requires a dependency on the Rust standard library.
+std = []
+
+# Provide `derive(JsonSchema)` macro.
 derive = ["schemars_derive"]
+
+# Preserves order of properties inserted into a `Schema`.
+# When deriving `JsonSchema`, this ensures that the `properties` entires match
+# the order of the fields in the struct definition.
 preserve_order  = ["serde_json/preserve_order"]
 
+# Implements `JsonSchema` on `serde_json::value::RawValue`
 raw_value = ["serde_json/raw_value"]
 
-ui_test = []
+# For internal/CI use only
+_ui_test = []
+
+[[test]]
+name = "std_time"
+required-features = ["std"]
+
+[[test]]
+name = "ffi"
+required-features = ["std"]
 
 [[test]]
 name = "ui"
-required-features = ["ui_test"]
+required-features = ["_ui_test"]
 
 [[test]]
 name = "chrono"
@@ -103,4 +122,4 @@ required-features = ["rust_decimal1", "bigdecimal04"]
 
 [package.metadata.docs.rs]
 all-features = true
-rustdoc-args = ["--extend-css", "docs-rs-custom.css "]
+rustdoc-args = ["--extend-css", "docs-rs-custom.css"]
diff --git a/schemars/src/_private.rs b/schemars/src/_private.rs
index f641c02..dc867d9 100644
--- a/schemars/src/_private.rs
+++ b/schemars/src/_private.rs
@@ -1,3 +1,4 @@
+use crate::_alloc_prelude::*;
 use crate::{JsonSchema, Schema, SchemaGenerator};
 use serde::Serialize;
 use serde_json::{json, map::Entry, Map, Value};
diff --git a/schemars/src/gen.rs b/schemars/src/gen.rs
index 5c1d77c..505baa6 100644
--- a/schemars/src/gen.rs
+++ b/schemars/src/gen.rs
@@ -8,14 +8,15 @@ There are two main types in this module:
 */
 
 use crate::Schema;
+use crate::_alloc_prelude::*;
 use crate::{transform::*, JsonSchema};
+use alloc::collections::{BTreeMap, BTreeSet};
+use core::{any::Any, fmt::Debug};
 use dyn_clone::DynClone;
 use serde::Serialize;
-use serde_json::{Map, Value};
-use std::collections::{HashMap, HashSet};
-use std::{any::Any, fmt::Debug};
+use serde_json::{Map as JsonMap, Value};
 
-type CowStr = std::borrow::Cow<'static, str>;
+type CowStr = alloc::borrow::Cow<'static, str>;
 
 /// Settings to customize how Schemas are generated.
 ///
@@ -168,10 +169,10 @@ impl SchemaSettings {
 #[derive(Debug, Default)]
 pub struct SchemaGenerator {
     settings: SchemaSettings,
-    definitions: Map<String, Value>,
-    pending_schema_ids: HashSet<CowStr>,
-    schema_id_to_name: HashMap<CowStr, CowStr>,
-    used_schema_names: HashSet<CowStr>,
+    definitions: JsonMap<String, Value>,
+    pending_schema_ids: BTreeSet<CowStr>,
+    schema_id_to_name: BTreeMap<CowStr, CowStr>,
+    used_schema_names: BTreeSet<CowStr>,
 }
 
 impl Clone for SchemaGenerator {
@@ -179,9 +180,9 @@ impl Clone for SchemaGenerator {
         Self {
             settings: self.settings.clone(),
             definitions: self.definitions.clone(),
-            pending_schema_ids: HashSet::new(),
-            schema_id_to_name: HashMap::new(),
-            used_schema_names: HashSet::new(),
+            pending_schema_ids: BTreeSet::new(),
+            schema_id_to_name: BTreeMap::new(),
+            used_schema_names: BTreeSet::new(),
         }
     }
 }
@@ -276,7 +277,7 @@ impl SchemaGenerator {
     ///
     /// The keys of the returned `Map` are the [schema names](JsonSchema::schema_name), and the values are the schemas
     /// themselves.
-    pub fn definitions(&self) -> &Map<String, Value> {
+    pub fn definitions(&self) -> &JsonMap<String, Value> {
         &self.definitions
     }
 
@@ -284,7 +285,7 @@ impl SchemaGenerator {
     ///
     /// The keys of the returned `Map` are the [schema names](JsonSchema::schema_name), and the values are the schemas
     /// themselves.
-    pub fn definitions_mut(&mut self) -> &mut Map<String, Value> {
+    pub fn definitions_mut(&mut self) -> &mut JsonMap<String, Value> {
         &mut self.definitions
     }
 
@@ -293,8 +294,8 @@ impl SchemaGenerator {
     ///
     /// The keys of the returned `Map` are the [schema names](JsonSchema::schema_name), and the values are the schemas
     /// themselves.
-    pub fn take_definitions(&mut self) -> Map<String, Value> {
-        std::mem::take(&mut self.definitions)
+    pub fn take_definitions(&mut self) -> JsonMap<String, Value> {
+        core::mem::take(&mut self.definitions)
     }
 
     /// Returns an iterator over the [transforms](SchemaSettings::transforms) being used by this `SchemaGenerator`.
@@ -338,7 +339,7 @@ impl SchemaGenerator {
             .entry("title")
             .or_insert_with(|| T::schema_name().into());
 
-        if let Some(meta_schema) = std::mem::take(&mut self.settings.meta_schema) {
+        if let Some(meta_schema) = core::mem::take(&mut self.settings.meta_schema) {
             object.insert("$schema".into(), meta_schema.into());
         }
 
@@ -401,7 +402,7 @@ impl SchemaGenerator {
             object.insert("examples".into(), vec![example].into());
         }
 
-        if let Some(meta_schema) = std::mem::take(&mut self.settings.meta_schema) {
+        if let Some(meta_schema) = core::mem::take(&mut self.settings.meta_schema) {
             object.insert("$schema".into(), meta_schema.into());
         }
 
@@ -440,8 +441,8 @@ impl SchemaGenerator {
 
     fn add_definitions(
         &mut self,
-        schema_object: &mut Map<String, Value>,
-        mut definitions: Map<String, Value>,
+        schema_object: &mut JsonMap<String, Value>,
+        mut definitions: JsonMap<String, Value>,
     ) {
         if definitions.is_empty() {
             return;
@@ -472,10 +473,10 @@ impl SchemaGenerator {
 }
 
 fn json_pointer_mut<'a>(
-    mut object: &'a mut Map<String, Value>,
+    mut object: &'a mut JsonMap<String, Value>,
     pointer: &str,
     create_if_missing: bool,
-) -> Option<&'a mut Map<String, Value>> {
+) -> Option<&'a mut JsonMap<String, Value>> {
     let pointer = pointer.strip_prefix('/')?;
     if pointer.is_empty() {
         return Some(object);
@@ -491,7 +492,7 @@ fn json_pointer_mut<'a>(
         use serde_json::map::Entry;
         let next_value = match object.entry(segment) {
             Entry::Occupied(o) => o.into_mut(),
-            Entry::Vacant(v) if create_if_missing => v.insert(Value::Object(Map::default())),
+            Entry::Vacant(v) if create_if_missing => v.insert(Value::Object(JsonMap::default())),
             Entry::Vacant(_) => return None,
         };
 
@@ -580,7 +581,7 @@ where
 }
 
 impl Debug for Box<dyn GenTransform> {
-    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
+    fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
         self._debug_type_name(f)
     }
 }
diff --git a/schemars/src/json_schema_impls/array.rs b/schemars/src/json_schema_impls/array.rs
index 7dccbfb..18e8b76 100644
--- a/schemars/src/json_schema_impls/array.rs
+++ b/schemars/src/json_schema_impls/array.rs
@@ -1,6 +1,7 @@
+use crate::_alloc_prelude::*;
 use crate::gen::SchemaGenerator;
 use crate::{json_schema, JsonSchema, Schema};
-use std::borrow::Cow;
+use alloc::borrow::Cow;
 
 // Does not require T: JsonSchema.
 impl<T> JsonSchema for [T; 0] {
diff --git a/schemars/src/json_schema_impls/arrayvec07.rs b/schemars/src/json_schema_impls/arrayvec07.rs
index cd5f154..a5511ab 100644
--- a/schemars/src/json_schema_impls/arrayvec07.rs
+++ b/schemars/src/json_schema_impls/arrayvec07.rs
@@ -1,3 +1,4 @@
+use crate::_alloc_prelude::*;
 use crate::gen::SchemaGenerator;
 use crate::{json_schema, JsonSchema, Schema};
 use arrayvec07::{ArrayString, ArrayVec};
@@ -12,7 +13,7 @@ where
 {
     always_inline!();
 
-    fn schema_name() -> std::borrow::Cow<'static, str> {
+    fn schema_name() -> alloc::borrow::Cow<'static, str> {
         format!("Array_up_to_size_{}_of_{}", CAP, T::schema_name()).into()
     }
 
diff --git a/schemars/src/json_schema_impls/atomic.rs b/schemars/src/json_schema_impls/atomic.rs
index 19d681c..e871e76 100644
--- a/schemars/src/json_schema_impls/atomic.rs
+++ b/schemars/src/json_schema_impls/atomic.rs
@@ -1,4 +1,4 @@
-use std::sync::atomic::*;
+use core::sync::atomic::*;
 
 #[cfg(target_has_atomic = "8")]
 forward_impl!(AtomicBool => bool);
diff --git a/schemars/src/json_schema_impls/chrono04.rs b/schemars/src/json_schema_impls/chrono04.rs
index 2635e56..1dfc2b1 100644
--- a/schemars/src/json_schema_impls/chrono04.rs
+++ b/schemars/src/json_schema_impls/chrono04.rs
@@ -1,7 +1,7 @@
 use crate::gen::SchemaGenerator;
 use crate::{json_schema, JsonSchema, Schema};
 use chrono04::prelude::*;
-use std::borrow::Cow;
+use alloc::borrow::Cow;
 
 impl JsonSchema for Weekday {
     always_inline!();
diff --git a/schemars/src/json_schema_impls/core.rs b/schemars/src/json_schema_impls/core.rs
index d49f392..3e0d994 100644
--- a/schemars/src/json_schema_impls/core.rs
+++ b/schemars/src/json_schema_impls/core.rs
@@ -1,8 +1,9 @@
+use crate::_alloc_prelude::*;
 use crate::gen::SchemaGenerator;
 use crate::{json_schema, JsonSchema, Schema};
+use alloc::borrow::Cow;
+use core::ops::{Bound, Range, RangeInclusive};
 use serde_json::Value;
-use std::borrow::Cow;
-use std::ops::{Bound, Range, RangeInclusive};
 
 impl<T: JsonSchema> JsonSchema for Option<T> {
     always_inline!();
@@ -32,8 +33,10 @@ impl<T: JsonSchema> JsonSchema for Option<T> {
                         }
                         Some(Value::String(string)) => {
                             if string != "null" {
-                                *instance_type.unwrap() =
-                                    Value::Array(vec![std::mem::take(string).into(), "null".into()])
+                                *instance_type.unwrap() = Value::Array(vec![
+                                    core::mem::take(string).into(),
+                                    "null".into(),
+                                ])
                             }
                             obj.into()
                         }
@@ -158,6 +161,6 @@ impl<T: JsonSchema> JsonSchema for Range<T> {
 
 forward_impl!((<T: JsonSchema> JsonSchema for RangeInclusive<T>) => Range<T>);
 
-forward_impl!((<T: ?Sized> JsonSchema for std::marker::PhantomData<T>) => ());
+forward_impl!((<T: ?Sized> JsonSchema for core::marker::PhantomData<T>) => ());
 
-forward_impl!((<'a> JsonSchema for std::fmt::Arguments<'a>) => String);
+forward_impl!((<'a> JsonSchema for core::fmt::Arguments<'a>) => String);
diff --git a/schemars/src/json_schema_impls/decimal.rs b/schemars/src/json_schema_impls/decimal.rs
index 3266ccc..0f55ba9 100644
--- a/schemars/src/json_schema_impls/decimal.rs
+++ b/schemars/src/json_schema_impls/decimal.rs
@@ -1,6 +1,6 @@
 use crate::gen::SchemaGenerator;
 use crate::{json_schema, JsonSchema, Schema};
-use std::borrow::Cow;
+use alloc::borrow::Cow;
 
 macro_rules! decimal_impl {
     ($type:ty) => {
diff --git a/schemars/src/json_schema_impls/either1.rs b/schemars/src/json_schema_impls/either1.rs
index fcc3479..3822faa 100644
--- a/schemars/src/json_schema_impls/either1.rs
+++ b/schemars/src/json_schema_impls/either1.rs
@@ -1,7 +1,8 @@
+use crate::_alloc_prelude::*;
 use crate::gen::SchemaGenerator;
 use crate::{json_schema, JsonSchema, Schema};
+use alloc::borrow::Cow;
 use either1::Either;
-use std::borrow::Cow;
 
 impl<L: JsonSchema, R: JsonSchema> JsonSchema for Either<L, R> {
     always_inline!();
diff --git a/schemars/src/json_schema_impls/ffi.rs b/schemars/src/json_schema_impls/ffi.rs
index 026d5ae..524c49f 100644
--- a/schemars/src/json_schema_impls/ffi.rs
+++ b/schemars/src/json_schema_impls/ffi.rs
@@ -1,6 +1,7 @@
+use crate::_alloc_prelude::*;
 use crate::gen::SchemaGenerator;
 use crate::{json_schema, JsonSchema, Schema};
-use std::borrow::Cow;
+use alloc::borrow::Cow;
 use std::ffi::{CStr, CString, OsStr, OsString};
 
 impl JsonSchema for OsString {
diff --git a/schemars/src/json_schema_impls/indexmap2.rs b/schemars/src/json_schema_impls/indexmap2.rs
index 9473dea..355864e 100644
--- a/schemars/src/json_schema_impls/indexmap2.rs
+++ b/schemars/src/json_schema_impls/indexmap2.rs
@@ -1,6 +1,6 @@
 use crate::JsonSchema;
+use alloc::collections::{BTreeMap, BTreeSet};
 use indexmap2::{IndexMap, IndexSet};
-use std::collections::{HashMap, HashSet};
 
-forward_impl!((<K, V: JsonSchema, H> JsonSchema for IndexMap<K, V, H>) => HashMap<K, V, H>);
-forward_impl!((<T: JsonSchema, H> JsonSchema for IndexSet<T, H>) => HashSet<T, H>);
+forward_impl!((<K, V: JsonSchema, H> JsonSchema for IndexMap<K, V, H>) => BTreeMap<K, V>);
+forward_impl!((<T: JsonSchema, H> JsonSchema for IndexSet<T, H>) => BTreeSet<T>);
diff --git a/schemars/src/json_schema_impls/maps.rs b/schemars/src/json_schema_impls/maps.rs
index 19ae5cf..af43a43 100644
--- a/schemars/src/json_schema_impls/maps.rs
+++ b/schemars/src/json_schema_impls/maps.rs
@@ -1,6 +1,7 @@
+use crate::_alloc_prelude::*;
 use crate::gen::SchemaGenerator;
 use crate::{json_schema, JsonSchema, Schema};
-use std::borrow::Cow;
+use alloc::borrow::Cow;
 
 macro_rules! map_impl {
     ($($desc:tt)+) => {
@@ -28,5 +29,7 @@ macro_rules! map_impl {
     };
 }
 
-map_impl!(<K, V> JsonSchema for std::collections::BTreeMap<K, V>);
+map_impl!(<K, V> JsonSchema for alloc::collections::BTreeMap<K, V>);
+
+#[cfg(feature = "std")]
 map_impl!(<K, V, H> JsonSchema for std::collections::HashMap<K, V, H>);
diff --git a/schemars/src/json_schema_impls/mod.rs b/schemars/src/json_schema_impls/mod.rs
index 6260b2b..a0287f7 100644
--- a/schemars/src/json_schema_impls/mod.rs
+++ b/schemars/src/json_schema_impls/mod.rs
@@ -13,11 +13,11 @@ macro_rules! forward_impl {
                 <$target>::always_inline_schema()
             }
 
-            fn schema_name() -> std::borrow::Cow<'static, str> {
+            fn schema_name() -> alloc::borrow::Cow<'static, str> {
                 <$target>::schema_name()
             }
 
-            fn schema_id() -> std::borrow::Cow<'static, str> {
+            fn schema_id() -> alloc::borrow::Cow<'static, str> {
                 <$target>::schema_id()
             }
 
@@ -41,27 +41,29 @@ macro_rules! forward_impl {
 
 mod array;
 mod core;
-mod ffi;
 mod maps;
 mod nonzero_signed;
 mod nonzero_unsigned;
 mod primitives;
 mod sequences;
 mod serdejson;
-mod time;
+mod std_time;
 mod tuple;
 mod wrapper;
 
 #[cfg(target_has_atomic)]
 mod atomic;
 
+#[cfg(feature = "std")]
+mod ffi;
+
 #[cfg(feature = "arrayvec07")]
 mod arrayvec07;
 
 #[cfg(feature = "bytes1")]
 mod bytes1 {
-    forward_impl!(bytes1::Bytes => Vec<u8>);
-    forward_impl!(bytes1::BytesMut => Vec<u8>);
+    forward_impl!(bytes1::Bytes => alloc::vec::Vec<u8>);
+    forward_impl!(bytes1::BytesMut => alloc::vec::Vec<u8>);
 }
 
 #[cfg(feature = "chrono04")]
@@ -74,7 +76,7 @@ mod decimal;
 mod either1;
 
 #[cfg(feature = "enumset1")]
-forward_impl!((<T: enumset1::EnumSetType + crate::JsonSchema> crate::JsonSchema for enumset1::EnumSet<T>) => std::collections::BTreeSet<T>);
+forward_impl!((<T: enumset1::EnumSetType + crate::JsonSchema> crate::JsonSchema for enumset1::EnumSet<T>) => alloc::collections::BTreeSet<T>);
 
 #[cfg(feature = "indexmap2")]
 mod indexmap2;
@@ -83,10 +85,10 @@ mod indexmap2;
 mod semver1;
 
 #[cfg(feature = "smallvec1")]
-forward_impl!((<A: smallvec1::Array> crate::JsonSchema for smallvec1::SmallVec<A> where A::Item: crate::JsonSchema) => Vec<A::Item>);
+forward_impl!((<A: smallvec1::Array> crate::JsonSchema for smallvec1::SmallVec<A> where A::Item: crate::JsonSchema) => alloc::vec::Vec<A::Item>);
 
 #[cfg(feature = "smol_str02")]
-forward_impl!(smol_str02::SmolStr => String);
+forward_impl!(smol_str02::SmolStr => alloc::string::String);
 
 #[cfg(feature = "url2")]
 mod url2;
diff --git a/schemars/src/json_schema_impls/nonzero_signed.rs b/schemars/src/json_schema_impls/nonzero_signed.rs
index c9d0919..37fef86 100644
--- a/schemars/src/json_schema_impls/nonzero_signed.rs
+++ b/schemars/src/json_schema_impls/nonzero_signed.rs
@@ -1,7 +1,8 @@
+use crate::_alloc_prelude::*;
 use crate::gen::SchemaGenerator;
 use crate::{JsonSchema, Schema};
-use std::borrow::Cow;
-use std::num::*;
+use alloc::borrow::Cow;
+use core::num::*;
 
 macro_rules! nonzero_unsigned_impl {
     ($type:ty => $primitive:ty) => {
diff --git a/schemars/src/json_schema_impls/nonzero_unsigned.rs b/schemars/src/json_schema_impls/nonzero_unsigned.rs
index afabc05..8c07fb3 100644
--- a/schemars/src/json_schema_impls/nonzero_unsigned.rs
+++ b/schemars/src/json_schema_impls/nonzero_unsigned.rs
@@ -1,8 +1,9 @@
+use crate::_alloc_prelude::*;
 use crate::gen::SchemaGenerator;
 use crate::JsonSchema;
 use crate::Schema;
-use std::borrow::Cow;
-use std::num::*;
+use alloc::borrow::Cow;
+use core::num::*;
 
 macro_rules! nonzero_unsigned_impl {
     ($type:ty => $primitive:ty) => {
diff --git a/schemars/src/json_schema_impls/primitives.rs b/schemars/src/json_schema_impls/primitives.rs
index a3bcce6..4b87961 100644
--- a/schemars/src/json_schema_impls/primitives.rs
+++ b/schemars/src/json_schema_impls/primitives.rs
@@ -1,8 +1,7 @@
+use crate::_alloc_prelude::*;
 use crate::gen::SchemaGenerator;
 use crate::{json_schema, JsonSchema, Schema};
-use std::borrow::Cow;
-use std::net::{IpAddr, Ipv4Addr, Ipv6Addr, SocketAddr, SocketAddrV4, SocketAddrV6};
-use std::path::{Path, PathBuf};
+use alloc::borrow::Cow;
 
 macro_rules! simple_impl {
     ($type:ty => $instance_type:literal) => {
@@ -51,16 +50,23 @@ simple_impl!(i128 => "integer", "int128");
 simple_impl!(isize => "integer", "int");
 simple_impl!(() => "null");
 
-simple_impl!(Path => "string");
-simple_impl!(PathBuf => "string");
+#[cfg(feature = "std")]
+mod std_types {
+    use super::*;
+    use std::net::{IpAddr, Ipv4Addr, Ipv6Addr, SocketAddr, SocketAddrV4, SocketAddrV6};
+    use std::path::{Path, PathBuf};
 
-simple_impl!(Ipv4Addr => "string", "ipv4");
-simple_impl!(Ipv6Addr => "string", "ipv6");
-simple_impl!(IpAddr => "string", "ip");
+    simple_impl!(Path => "string");
+    simple_impl!(PathBuf => "string");
 
-simple_impl!(SocketAddr => "string");
-simple_impl!(SocketAddrV4 => "string");
-simple_impl!(SocketAddrV6 => "string");
+    simple_impl!(Ipv4Addr => "string", "ipv4");
+    simple_impl!(Ipv6Addr => "string", "ipv6");
+    simple_impl!(IpAddr => "string", "ip");
+
+    simple_impl!(SocketAddr => "string");
+    simple_impl!(SocketAddrV4 => "string");
+    simple_impl!(SocketAddrV6 => "string");
+}
 
 macro_rules! unsigned_impl {
     ($type:ty => $instance_type:literal, $format:literal) => {
diff --git a/schemars/src/json_schema_impls/semver1.rs b/schemars/src/json_schema_impls/semver1.rs
index eb121fb..d693bd6 100644
--- a/schemars/src/json_schema_impls/semver1.rs
+++ b/schemars/src/json_schema_impls/semver1.rs
@@ -1,7 +1,7 @@
 use crate::gen::SchemaGenerator;
 use crate::{json_schema, JsonSchema, Schema};
 use semver1::Version;
-use std::borrow::Cow;
+use alloc::borrow::Cow;
 
 impl JsonSchema for Version {
     always_inline!();
diff --git a/schemars/src/json_schema_impls/sequences.rs b/schemars/src/json_schema_impls/sequences.rs
index c131339..8241dac 100644
--- a/schemars/src/json_schema_impls/sequences.rs
+++ b/schemars/src/json_schema_impls/sequences.rs
@@ -1,6 +1,7 @@
+use crate::_alloc_prelude::*;
 use crate::gen::SchemaGenerator;
 use crate::{json_schema, JsonSchema, Schema};
-use std::borrow::Cow;
+use alloc::borrow::Cow;
 
 macro_rules! seq_impl {
     ($($desc:tt)+) => {
@@ -55,11 +56,13 @@ macro_rules! set_impl {
     };
 }
 
-seq_impl!(<T> JsonSchema for std::collections::BinaryHeap<T>);
-seq_impl!(<T> JsonSchema for std::collections::LinkedList<T>);
+seq_impl!(<T> JsonSchema for alloc::collections::BinaryHeap<T>);
+seq_impl!(<T> JsonSchema for alloc::collections::LinkedList<T>);
 seq_impl!(<T> JsonSchema for [T]);
-seq_impl!(<T> JsonSchema for Vec<T>);
-seq_impl!(<T> JsonSchema for std::collections::VecDeque<T>);
+seq_impl!(<T> JsonSchema for alloc::vec::Vec<T>);
+seq_impl!(<T> JsonSchema for alloc::collections::VecDeque<T>);
 
-set_impl!(<T> JsonSchema for std::collections::BTreeSet<T>);
+set_impl!(<T> JsonSchema for alloc::collections::BTreeSet<T>);
+
+#[cfg(feature = "std")]
 set_impl!(<T, H> JsonSchema for std::collections::HashSet<T, H>);
diff --git a/schemars/src/json_schema_impls/serdejson.rs b/schemars/src/json_schema_impls/serdejson.rs
index cd25326..25f6e78 100644
--- a/schemars/src/json_schema_impls/serdejson.rs
+++ b/schemars/src/json_schema_impls/serdejson.rs
@@ -1,8 +1,9 @@
+use crate::_alloc_prelude::*;
 use crate::gen::SchemaGenerator;
 use crate::{json_schema, JsonSchema, Schema};
+use alloc::borrow::Cow;
+use alloc::collections::BTreeMap;
 use serde_json::{Map, Number, Value};
-use std::borrow::Cow;
-use std::collections::BTreeMap;
 
 impl JsonSchema for Value {
     always_inline!();
diff --git a/schemars/src/json_schema_impls/time.rs b/schemars/src/json_schema_impls/std_time.rs
similarity index 88%
rename from schemars/src/json_schema_impls/time.rs
rename to schemars/src/json_schema_impls/std_time.rs
index 0f1eb74..1766e93 100644
--- a/schemars/src/json_schema_impls/time.rs
+++ b/schemars/src/json_schema_impls/std_time.rs
@@ -1,9 +1,8 @@
 use crate::gen::SchemaGenerator;
 use crate::{json_schema, JsonSchema, Schema};
-use std::borrow::Cow;
-use std::time::{Duration, SystemTime};
+use alloc::borrow::Cow;
 
-impl JsonSchema for Duration {
+impl JsonSchema for core::time::Duration {
     fn schema_name() -> Cow<'static, str> {
         "Duration".into()
     }
@@ -24,7 +23,8 @@ impl JsonSchema for Duration {
     }
 }
 
-impl JsonSchema for SystemTime {
+#[cfg(feature = "std")]
+impl JsonSchema for std::time::SystemTime {
     fn schema_name() -> Cow<'static, str> {
         "SystemTime".into()
     }
diff --git a/schemars/src/json_schema_impls/tuple.rs b/schemars/src/json_schema_impls/tuple.rs
index c05a5f8..bb57c0e 100644
--- a/schemars/src/json_schema_impls/tuple.rs
+++ b/schemars/src/json_schema_impls/tuple.rs
@@ -1,6 +1,7 @@
+use crate::_alloc_prelude::*;
 use crate::gen::SchemaGenerator;
 use crate::{json_schema, JsonSchema, Schema};
-use std::borrow::Cow;
+use alloc::borrow::Cow;
 
 macro_rules! tuple_impls {
     ($($len:expr => ($($name:ident)+))+) => {
diff --git a/schemars/src/json_schema_impls/url2.rs b/schemars/src/json_schema_impls/url2.rs
index 5a467d9..d34e949 100644
--- a/schemars/src/json_schema_impls/url2.rs
+++ b/schemars/src/json_schema_impls/url2.rs
@@ -1,6 +1,6 @@
 use crate::gen::SchemaGenerator;
 use crate::{json_schema, JsonSchema, Schema};
-use std::borrow::Cow;
+use alloc::borrow::Cow;
 use url2::Url;
 
 impl JsonSchema for Url {
diff --git a/schemars/src/json_schema_impls/uuid1.rs b/schemars/src/json_schema_impls/uuid1.rs
index a56c10c..2628f00 100644
--- a/schemars/src/json_schema_impls/uuid1.rs
+++ b/schemars/src/json_schema_impls/uuid1.rs
@@ -1,6 +1,6 @@
 use crate::gen::SchemaGenerator;
 use crate::{json_schema, JsonSchema, Schema};
-use std::borrow::Cow;
+use alloc::borrow::Cow;
 use uuid1::Uuid;
 
 impl JsonSchema for Uuid {
diff --git a/schemars/src/json_schema_impls/wrapper.rs b/schemars/src/json_schema_impls/wrapper.rs
index e7e233c..ea09504 100644
--- a/schemars/src/json_schema_impls/wrapper.rs
+++ b/schemars/src/json_schema_impls/wrapper.rs
@@ -1,4 +1,5 @@
 use crate::JsonSchema;
+use crate::_alloc_prelude::*;
 
 macro_rules! wrapper_impl {
     ($($desc:tt)+) => {
@@ -9,14 +10,16 @@ macro_rules! wrapper_impl {
 wrapper_impl!(<'a, T: ?Sized> JsonSchema for &'a T);
 wrapper_impl!(<'a, T: ?Sized> JsonSchema for &'a mut T);
 wrapper_impl!(<T: ?Sized> JsonSchema for Box<T>);
-wrapper_impl!(<T: ?Sized> JsonSchema for std::rc::Rc<T>);
-wrapper_impl!(<T: ?Sized> JsonSchema for std::rc::Weak<T>);
-wrapper_impl!(<T: ?Sized> JsonSchema for std::sync::Arc<T>);
-wrapper_impl!(<T: ?Sized> JsonSchema for std::sync::Weak<T>);
+wrapper_impl!(<T: ?Sized> JsonSchema for alloc::rc::Rc<T>);
+wrapper_impl!(<T: ?Sized> JsonSchema for alloc::rc::Weak<T>);
+wrapper_impl!(<T: ?Sized> JsonSchema for alloc::sync::Arc<T>);
+wrapper_impl!(<T: ?Sized> JsonSchema for alloc::sync::Weak<T>);
+#[cfg(feature = "std")]
 wrapper_impl!(<T: ?Sized> JsonSchema for std::sync::Mutex<T>);
+#[cfg(feature = "std")]
 wrapper_impl!(<T: ?Sized> JsonSchema for std::sync::RwLock<T>);
-wrapper_impl!(<T: ?Sized> JsonSchema for std::cell::Cell<T>);
-wrapper_impl!(<T: ?Sized> JsonSchema for std::cell::RefCell<T>);
-wrapper_impl!(<'a, T: ?Sized + ToOwned> JsonSchema for std::borrow::Cow<'a, T>);
-wrapper_impl!(<T> JsonSchema for std::num::Wrapping<T>);
-wrapper_impl!(<T> JsonSchema for std::cmp::Reverse<T>);
+wrapper_impl!(<T: ?Sized> JsonSchema for core::cell::Cell<T>);
+wrapper_impl!(<T: ?Sized> JsonSchema for core::cell::RefCell<T>);
+wrapper_impl!(<'a, T: ?Sized + ToOwned> JsonSchema for alloc::borrow::Cow<'a, T>);
+wrapper_impl!(<T> JsonSchema for core::num::Wrapping<T>);
+wrapper_impl!(<T> JsonSchema for core::cmp::Reverse<T>);
diff --git a/schemars/src/lib.rs b/schemars/src/lib.rs
index c0c316a..186a53f 100644
--- a/schemars/src/lib.rs
+++ b/schemars/src/lib.rs
@@ -1,5 +1,10 @@
 #![deny(unsafe_code)]
 #![doc = include_str!("../README.md")]
+#![no_std]
+
+extern crate alloc;
+#[cfg(feature = "std")]
+extern crate std;
 
 mod json_schema_impls;
 mod schema;
@@ -16,18 +21,29 @@ pub mod transform;
 
 #[cfg(feature = "schemars_derive")]
 extern crate schemars_derive;
-use std::borrow::Cow;
+use alloc::borrow::Cow;
 
 #[cfg(feature = "schemars_derive")]
 pub use schemars_derive::*;
 
-// Export serde_json so schemars_derive can use it
+// Export crates so schemars_derive can use them
+#[doc(hidden)]
+pub extern crate alloc as _alloc;
 #[doc(hidden)]
-pub use serde_json as _serde_json;
+pub extern crate serde_json as _serde_json;
 
 pub use gen::SchemaGenerator;
 pub use schema::Schema;
 
+mod _alloc_prelude {
+    pub use alloc::borrow::ToOwned;
+    pub use alloc::boxed::Box;
+    pub use alloc::format;
+    pub use alloc::string::{String, ToString};
+    pub use alloc::vec;
+    pub use alloc::vec::Vec;
+}
+
 /// A type which can be described as a JSON Schema document.
 ///
 /// This is implemented for many Rust primitive and standard library types.
diff --git a/schemars/src/schema.rs b/schemars/src/schema.rs
index dd9e866..c3882d0 100644
--- a/schemars/src/schema.rs
+++ b/schemars/src/schema.rs
@@ -2,6 +2,7 @@
 JSON Schema types.
 */
 
+use crate::_alloc_prelude::*;
 use ref_cast::{ref_cast_custom, RefCastCustom};
 use serde::{Deserialize, Serialize};
 use serde_json::{Map, Value};
@@ -186,7 +187,7 @@ impl From<Schema> for Value {
     }
 }
 
-impl std::convert::TryFrom<Value> for Schema {
+impl core::convert::TryFrom<Value> for Schema {
     type Error = serde_json::Error;
 
     fn try_from(value: Value) -> serde_json::Result<Schema> {
@@ -195,7 +196,7 @@ impl std::convert::TryFrom<Value> for Schema {
     }
 }
 
-impl<'a> std::convert::TryFrom<&'a Value> for &'a Schema {
+impl<'a> core::convert::TryFrom<&'a Value> for &'a Schema {
     type Error = serde_json::Error;
 
     fn try_from(value: &Value) -> serde_json::Result<&Schema> {
@@ -204,7 +205,7 @@ impl<'a> std::convert::TryFrom<&'a Value> for &'a Schema {
     }
 }
 
-impl<'a> std::convert::TryFrom<&'a mut Value> for &'a mut Schema {
+impl<'a> core::convert::TryFrom<&'a mut Value> for &'a mut Schema {
     type Error = serde_json::Error;
 
     fn try_from(value: &mut Value) -> serde_json::Result<&mut Schema> {
@@ -232,11 +233,11 @@ impl From<bool> for Schema {
 }
 
 impl crate::JsonSchema for Schema {
-    fn schema_name() -> std::borrow::Cow<'static, str> {
+    fn schema_name() -> alloc::borrow::Cow<'static, str> {
         "Schema".into()
     }
 
-    fn schema_id() -> std::borrow::Cow<'static, str> {
+    fn schema_id() -> alloc::borrow::Cow<'static, str> {
         "schemars::Schema".into()
     }
 
diff --git a/schemars/src/ser.rs b/schemars/src/ser.rs
index f42c187..c0bcc21 100644
--- a/schemars/src/ser.rs
+++ b/schemars/src/ser.rs
@@ -1,6 +1,7 @@
+use crate::_alloc_prelude::*;
 use crate::{json_schema, JsonSchema, Schema, SchemaGenerator};
+use core::fmt::Display;
 use serde_json::{Error, Map, Value};
-use std::fmt::Display;
 
 pub(crate) struct Serializer<'a> {
     pub(crate) gen: &'a mut SchemaGenerator,
@@ -142,8 +143,10 @@ impl<'a> serde::Serializer for Serializer<'a> {
                         }
                         Some(Value::String(string)) => {
                             if string != "null" {
-                                *value.unwrap() =
-                                    Value::Array(vec![std::mem::take(string).into(), "null".into()])
+                                *value.unwrap() = Value::Array(vec![
+                                    core::mem::take(string).into(),
+                                    "null".into(),
+                                ])
                             }
                             obj.into()
                         }
diff --git a/schemars/src/transform.rs b/schemars/src/transform.rs
index 7482b31..5529e06 100644
--- a/schemars/src/transform.rs
+++ b/schemars/src/transform.rs
@@ -112,9 +112,9 @@ assert_eq!(
 ```
 
 */
-use serde_json::{json, Value};
-
 use crate::Schema;
+use crate::_alloc_prelude::*;
+use serde_json::{json, Value};
 
 /// Trait used to modify a constructed schema and optionally its subschemas.
 ///
@@ -128,8 +128,8 @@ pub trait Transform {
     // Not public API
     // Hack to enable implementing Debug on Box<dyn GenTransform> even though closures don't implement Debug
     #[doc(hidden)]
-    fn _debug_type_name(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
-        f.write_str(std::any::type_name::<Self>())
+    fn _debug_type_name(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
+        f.write_str(core::any::type_name::<Self>())
     }
 }
 
diff --git a/schemars_derive/src/attr/validation.rs b/schemars_derive/src/attr/validation.rs
index 8d90302..095590a 100644
--- a/schemars_derive/src/attr/validation.rs
+++ b/schemars_derive/src/attr/validation.rs
@@ -155,7 +155,7 @@ impl ValidationAttrs {
                                 if !ignore_errors {
                                     errors.error_spanned_by(
                                         meta,
-                                        "unknown item in schemars length attribute".to_string(),
+                                        "unknown item in schemars length attribute",
                                     );
                                 }
                             }
@@ -184,7 +184,7 @@ impl ValidationAttrs {
                                 if !ignore_errors {
                                     errors.error_spanned_by(
                                         meta,
-                                        "unknown item in schemars range attribute".to_string(),
+                                        "unknown item in schemars range attribute",
                                     );
                                 }
                             }
@@ -252,8 +252,7 @@ impl ValidationAttrs {
                                         if !ignore_errors {
                                             errors.error_spanned_by(
                                                 meta,
-                                                "unknown item in schemars regex attribute"
-                                                    .to_string(),
+                                                "unknown item in schemars regex attribute",
                                             );
                                         }
                                     }
@@ -294,8 +293,7 @@ impl ValidationAttrs {
                                         if !ignore_errors {
                                             errors.error_spanned_by(
                                                 meta,
-                                                "unknown item in schemars contains attribute"
-                                                    .to_string(),
+                                                "unknown item in schemars contains attribute",
                                             );
                                         }
                                     }
@@ -390,7 +388,7 @@ impl ValidationAttrs {
         if let Some(format) = &self.format {
             let f = format.schema_str();
             result.push(quote! {
-                schema.ensure_object().insert("format".to_owned(), #f.into());
+                schema.ensure_object().insert("format".into(), #f.into());
             })
         };
 
diff --git a/schemars_derive/src/lib.rs b/schemars_derive/src/lib.rs
index bd427bd..1e9de01 100644
--- a/schemars_derive/src/lib.rs
+++ b/schemars_derive/src/lib.rs
@@ -60,11 +60,11 @@ fn derive_json_schema(mut input: syn::DeriveInput, repr: bool) -> syn::Result<To
                         <#ty as schemars::JsonSchema>::always_inline_schema()
                     }
 
-                    fn schema_name() -> std::borrow::Cow<'static, str> {
+                    fn schema_name() -> schemars::_alloc::borrow::Cow<'static, str> {
                         <#ty as schemars::JsonSchema>::schema_name()
                     }
 
-                    fn schema_id() -> std::borrow::Cow<'static, str> {
+                    fn schema_id() -> schemars::_alloc::borrow::Cow<'static, str> {
                         <#ty as schemars::JsonSchema>::schema_id()
                     }
 
@@ -104,11 +104,11 @@ fn derive_json_schema(mut input: syn::DeriveInput, repr: bool) -> syn::Result<To
     {
         (
             quote! {
-                std::borrow::Cow::Borrowed(#schema_base_name)
+                schemars::_alloc::borrow::Cow::Borrowed(#schema_base_name)
             },
             quote! {
-                std::borrow::Cow::Borrowed(std::concat!(
-                    std::module_path!(),
+                schemars::_alloc::borrow::Cow::Borrowed(::core::concat!(
+                    ::core::module_path!(),
                     "::",
                     #schema_base_name
                 ))
@@ -121,15 +121,15 @@ fn derive_json_schema(mut input: syn::DeriveInput, repr: bool) -> syn::Result<To
         }
         (
             quote! {
-                std::borrow::Cow::Owned(
-                    format!(#schema_name_fmt #(,#type_params=#type_params::schema_name())* #(,#const_params=#const_params)*)
+                schemars::_alloc::borrow::Cow::Owned(
+                    schemars::_alloc::format!(#schema_name_fmt #(,#type_params=#type_params::schema_name())* #(,#const_params=#const_params)*)
                 )
             },
             quote! {
-                std::borrow::Cow::Owned(
-                    format!(
-                        std::concat!(
-                            std::module_path!(),
+                schemars::_alloc::borrow::Cow::Owned(
+                    schemars::_alloc::format!(
+                        ::core::concat!(
+                            ::core::module_path!(),
                             "::",
                             #schema_name_fmt
                         )
@@ -145,15 +145,15 @@ fn derive_json_schema(mut input: syn::DeriveInput, repr: bool) -> syn::Result<To
         schema_name_fmt.push_str(&"_and_{}".repeat(params.len() - 1));
         (
             quote! {
-                std::borrow::Cow::Owned(
-                    format!(#schema_name_fmt #(,#type_params::schema_name())* #(,#const_params)*)
+                schemars::_alloc::borrow::Cow::Owned(
+                    schemars::_alloc::format!(#schema_name_fmt #(,#type_params::schema_name())* #(,#const_params)*)
                 )
             },
             quote! {
-                std::borrow::Cow::Owned(
-                    format!(
-                        std::concat!(
-                            std::module_path!(),
+                schemars::_alloc::borrow::Cow::Owned(
+                    schemars::_alloc::format!(
+                        ::core::concat!(
+                            ::core::module_path!(),
                             "::",
                             #schema_name_fmt
                         )
@@ -178,11 +178,11 @@ fn derive_json_schema(mut input: syn::DeriveInput, repr: bool) -> syn::Result<To
             #[automatically_derived]
             #[allow(unused_braces)]
             impl #impl_generics schemars::JsonSchema for #type_name #ty_generics #where_clause {
-                fn schema_name() -> std::borrow::Cow<'static, str> {
+                fn schema_name() -> schemars::_alloc::borrow::Cow<'static, str> {
                     #schema_name
                 }
 
-                fn schema_id() -> std::borrow::Cow<'static, str> {
+                fn schema_id() -> schemars::_alloc::borrow::Cow<'static, str> {
                     #schema_id
                 }
 
diff --git a/schemars_derive/src/schema_exprs.rs b/schemars_derive/src/schema_exprs.rs
index 3278e99..58aaded 100644
--- a/schemars_derive/src/schema_exprs.rs
+++ b/schemars_derive/src/schema_exprs.rs
@@ -51,11 +51,11 @@ pub fn expr_for_repr(cont: &Container) -> Result<TokenStream, syn::Error> {
 
     let mut schema_expr = quote!({
         let mut map = schemars::_serde_json::Map::new();
-        map.insert("type".to_owned(), "integer".into());
+        map.insert("type".into(), "integer".into());
         map.insert(
-            "enum".to_owned(),
+            "enum".into(),
             schemars::_serde_json::Value::Array({
-                let mut enum_values = Vec::new();
+                let mut enum_values = schemars::_alloc::vec::Vec::new();
                 #(enum_values.push((#enum_ident::#variant_idents as #repr_type).into());)*
                 enum_values
             }),
@@ -114,14 +114,14 @@ fn type_for_schema(with_attr: &WithAttr) -> (syn::Type, Option<TokenStream>) {
                         true
                     }
 
-                    fn schema_name() -> std::borrow::Cow<'static, str> {
-                        std::borrow::Cow::Borrowed(#fn_name)
+                    fn schema_name() -> schemars::_alloc::borrow::Cow<'static, str> {
+                        schemars::_alloc::borrow::Cow::Borrowed(#fn_name)
                     }
 
-                    fn schema_id() -> std::borrow::Cow<'static, str> {
-                        std::borrow::Cow::Borrowed(std::concat!(
+                    fn schema_id() -> schemars::_alloc::borrow::Cow<'static, str> {
+                        schemars::_alloc::borrow::Cow::Borrowed(::core::concat!(
                             "_SchemarsSchemaWithFunction/",
-                            std::module_path!(),
+                            ::core::module_path!(),
                             "/",
                             #fn_name
                         ))
@@ -171,11 +171,11 @@ fn expr_for_external_tagged_enum<'a>(
     let unit_names = unit_variants.iter().map(|v| v.name());
     let unit_schema = quote!({
         let mut map = schemars::_serde_json::Map::new();
-        map.insert("type".to_owned(), "string".into());
+        map.insert("type".into(), "string".into());
         map.insert(
-            "enum".to_owned(),
+            "enum".into(),
             schemars::_serde_json::Value::Array({
-                let mut enum_values = Vec::new();
+                let mut enum_values = schemars::_alloc::vec::Vec::new();
                 #(enum_values.push((#unit_names).into());)*
                 enum_values
             }),
@@ -347,9 +347,9 @@ fn variant_subschemas(unique: bool, schemas: Vec<TokenStream>) -> TokenStream {
     quote!({
         let mut map = schemars::_serde_json::Map::new();
         map.insert(
-            #keyword.to_owned(),
+            #keyword.into(),
             schemars::_serde_json::Value::Array({
-                let mut enum_values = Vec::new();
+                let mut enum_values = schemars::_alloc::vec::Vec::new();
                 #(enum_values.push(#schemas.to_value());)*
                 enum_values
             }),
@@ -556,7 +556,7 @@ fn field_default_expr(field: &Field, container_has_default: bool) -> Option<Toke
 
                 impl serde::Serialize for _SchemarsDefaultSerialize<#ty>
                 {
-                    fn serialize<S>(&self, serializer: S) -> core::result::Result<S::Ok, S::Error>
+                    fn serialize<S>(&self, serializer: S) -> ::core::result::Result<S::Ok, S::Error>
                     where
                         S: serde::Serializer
                     {


Test patch:
diff --git a/schemars/tests/expected/no_std.json b/schemars/tests/expected/no_std.json
new file mode 100644
index 0000000..68da890
--- /dev/null
+++ b/schemars/tests/expected/no_std.json
@@ -0,0 +1,70 @@
+{
+  "$schema": "https://json-schema.org/draft/2020-12/schema",
+  "title": "MyStruct",
+  "type": "object",
+  "properties": {
+    "my_int": {
+      "type": "integer",
+      "format": "int32"
+    },
+    "my_bool": {
+      "type": "boolean"
+    },
+    "my_nullable_enum": {
+      "anyOf": [
+        {
+          "$ref": "#/$defs/MyEnum"
+        },
+        {
+          "type": "null"
+        }
+      ]
+    }
+  },
+  "required": [
+    "my_int",
+    "my_bool"
+  ],
+  "$defs": {
+    "MyEnum": {
+      "oneOf": [
+        {
+          "type": "object",
+          "properties": {
+            "StringNewType": {
+              "type": "string"
+            }
+          },
+          "required": [
+            "StringNewType"
+          ],
+          "additionalProperties": false
+        },
+        {
+          "type": "object",
+          "properties": {
+            "StructVariant": {
+              "type": "object",
+              "properties": {
+                "floats": {
+                  "type": "array",
+                  "items": {
+                    "type": "number",
+                    "format": "float"
+                  }
+                }
+              },
+              "required": [
+                "floats"
+              ]
+            }
+          },
+          "required": [
+            "StructVariant"
+          ],
+          "additionalProperties": false
+        }
+      ]
+    }
+  }
+}
\ No newline at end of file
diff --git a/schemars/tests/no_std.rs b/schemars/tests/no_std.rs
new file mode 100644
index 0000000..c011aa2
--- /dev/null
+++ b/schemars/tests/no_std.rs
@@ -0,0 +1,25 @@
+#![no_std]
+
+mod util;
+use schemars::JsonSchema;
+use util::*;
+
+extern crate alloc as test_alloc;
+
+#[derive(JsonSchema)]
+pub struct MyStruct {
+    pub my_int: i32,
+    pub my_bool: bool,
+    pub my_nullable_enum: Option<MyEnum>,
+}
+
+#[derive(JsonSchema)]
+pub enum MyEnum {
+    StringNewType(test_alloc::string::String),
+    StructVariant { floats: test_alloc::vec::Vec<f32> },
+}
+
+#[test]
+fn no_std() -> TestResult {
+    test_default_generated_schema::<MyStruct>("no_std")
+}
diff --git a/schemars/tests/remote_derive_generic.rs b/schemars/tests/remote_derive_generic.rs
index 8599266..53fb7d2 100644
--- a/schemars/tests/remote_derive_generic.rs
+++ b/schemars/tests/remote_derive_generic.rs
@@ -2,7 +2,7 @@ mod util;
 
 use schemars::JsonSchema;
 use serde::Serialize;
-use std::collections::{HashMap, HashSet};
+use std::collections::{BTreeMap, BTreeSet};
 use util::*;
 
 #[allow(dead_code)]
@@ -39,7 +39,7 @@ struct MyStruct<'a, T: Serialize> {
     s: Str<'a>,
     // #[schemars(with = "HashMap::<_, HashSet<_>>")]
     // map: BTreeMap<String, BTreeSet<String>>,
-    #[schemars(with = "HashMap::<String, HashSet<String>>")]
+    #[schemars(with = "BTreeMap::<String, BTreeSet<String>>")]
     fake_map: (),
 }
 
diff --git a/schemars/tests/time.rs b/schemars/tests/std_time.rs
similarity index 100%
rename from schemars/tests/time.rs
rename to schemars/tests/std_time.rs
diff --git a/schemars/tests/util/mod.rs b/schemars/tests/util/mod.rs
index 3376c02..2c735ef 100644
--- a/schemars/tests/util/mod.rs
+++ b/schemars/tests/util/mod.rs
@@ -1,7 +1,11 @@
 use pretty_assertions::assert_eq;
 use schemars::{gen::SchemaSettings, schema_for, JsonSchema, Schema};
 use std::error::Error;
+use std::format;
 use std::fs;
+use std::prelude::rust_2021::*;
+
+extern crate std;
 
 pub type TestResult = Result<(), Box<dyn Error>>;
 
diff --git a/schemars/tests/validate.rs b/schemars/tests/validate.rs
index 9770eec..560fd57 100644
--- a/schemars/tests/validate.rs
+++ b/schemars/tests/validate.rs
@@ -1,6 +1,6 @@
 mod util;
 use schemars::JsonSchema;
-use std::collections::HashMap;
+use std::collections::BTreeMap;
 use util::*;
 
 // In real code, this would typically be a Regex, potentially created in a `lazy_static!`.
@@ -39,7 +39,7 @@ pub struct Struct {
     #[validate(length(equal = 2))]
     pair: Vec<i32>,
     #[validate(contains = "map_key")]
-    map_contains: HashMap<String, ()>,
+    map_contains: BTreeMap<String, ()>,
     #[validate(required)]
     required_option: Option<bool>,
     #[validate(required)]
@@ -91,7 +91,7 @@ pub struct Struct2 {
     #[schemars(length(equal = 2))]
     pair: Vec<i32>,
     #[schemars(contains = "map_key")]
-    map_contains: HashMap<String, ()>,
+    map_contains: BTreeMap<String, ()>,
     #[schemars(required)]
     required_option: Option<bool>,
     #[schemars(required)]