Skip to content

Commit 4bf9cf8

Browse files
committed
Make the rustls dependency optional
This commit puts the load_native_certs function behind a cargo feature that's turned on by default. Fixes #2
1 parent 6565fce commit 4bf9cf8

File tree

4 files changed

+68
-44
lines changed

4 files changed

+68
-44
lines changed

Cargo.toml

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,14 +11,17 @@ repository = "https://github.com/ctz/rustls-native-certs"
1111
categories = ["network-programming", "cryptography"]
1212

1313
[dependencies]
14-
rustls = "0.18.0"
14+
rustls = { version = "0.18.0", optional = true }
1515

1616
[dev-dependencies]
1717
webpki = "0.21"
1818
webpki-roots = "0"
1919
ring = "0.16.5"
2020
untrusted = "0.7.0"
2121

22+
[features]
23+
default = ["rustls"]
24+
2225
[target.'cfg(windows)'.dependencies]
2326
schannel = "0.1.15"
2427

admin/pipelines/cargo-steps.yml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
11
steps:
22
- script: cargo build
33
displayName: "cargo build (debug; default features)"
4+
- script: cargo build --no-default-features
5+
displayName: "cargo build (debug; no default features)"
46
- script: cargo test
57
displayName: "cargo test (debug; default features)"
68
env: { "RUST_BACKTRACE": "1" }

src/lib.rs

Lines changed: 15 additions & 43 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,14 @@
11
//! rustls-native-certs allows rustls to use the platform's native certificate
22
//! store when operating as a TLS client.
33
//!
4-
//! It consists of a single function [load_native_certs](fn.load_native_certs.html) which returns a
5-
//! `rustls::RootCertStore` pre-filled from the native certificate store.
6-
7-
/// Like `Result<T,E>`, but allows for functions that can return partially complete
8-
/// work alongside an error.
9-
pub type PartialResult<T, E> = Result<T, (Option<T>, E)>;
4+
//! It provides the following functions:
5+
//! * A higher level function [load_native_certs](fn.build_native_certs.html)
6+
//! which returns a `rustls::RootCertStore` pre-filled from the native
7+
//! certificate store. It is only available if the `rustls` feature is
8+
//! enabled.
9+
//! * A lower level function [build_native_certs](fn.build_native_certs.html)
10+
//! that lets callers pass their own certificate parsing logic. It is
11+
//! available to all users.
1012
1113
#[cfg(all(unix, not(target_os = "macos")))]
1214
mod unix;
@@ -23,50 +25,20 @@ mod macos;
2325
#[cfg(target_os = "macos")]
2426
use macos as platform;
2527

26-
use rustls::RootCertStore;
27-
use std::io::{Error, ErrorKind};
28+
#[cfg(feature = "rustls")]
29+
mod rustls;
30+
31+
use std::io::Error;
2832
use std::io::BufRead;
2933

34+
#[cfg(feature = "rustls")]
35+
pub use crate::rustls::{load_native_certs, PartialResult};
36+
3037
pub trait RootStoreBuilder {
3138
fn load_der(&mut self, der: Vec<u8>) -> Result<(), Error>;
3239
fn load_pem_file(&mut self, rd: &mut dyn BufRead) -> Result<(), Error>;
3340
}
3441

35-
/// Loads root certificates found in the platform's native certificate
36-
/// store.
37-
///
38-
/// On success, this returns a `rustls::RootCertStore` loaded with a
39-
/// snapshop of the root certificates found on this platform. This
40-
/// function fails in a platform-specific way, expressed in a `std::io::Error`.
41-
///
42-
/// This function can be expensive: on some platforms it involves loading
43-
/// and parsing a ~300KB disk file. It's therefore prudent to call
44-
/// this sparingly.
45-
pub fn load_native_certs() -> PartialResult<RootCertStore, Error> {
46-
struct RootCertStoreLoader {
47-
store: RootCertStore,
48-
};
49-
impl RootStoreBuilder for RootCertStoreLoader {
50-
fn load_der(&mut self, der: Vec<u8>) -> Result<(), Error> {
51-
self.store.add(&rustls::Certificate(der))
52-
.map_err(|err| Error::new(ErrorKind::InvalidData, err))
53-
}
54-
fn load_pem_file(&mut self, rd: &mut dyn BufRead) -> Result<(), Error> {
55-
self.store.add_pem_file(rd)
56-
.map(|_| ())
57-
.map_err(|()| Error::new(ErrorKind::InvalidData, format!("could not load PEM file")))
58-
}
59-
}
60-
let mut loader = RootCertStoreLoader {
61-
store: RootCertStore::empty(),
62-
};
63-
match build_native_certs(&mut loader) {
64-
Err(err) if loader.store.is_empty() => Err((None, err)),
65-
Err(err) => Err((Some(loader.store), err)),
66-
Ok(()) => Ok(loader.store),
67-
}
68-
}
69-
7042
/// Loads root certificates found in the platform's native certificate
7143
/// store, executing callbacks on the provided builder.
7244
///

src/rustls.rs

Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
use rustls::RootCertStore;
2+
use std::io::{Error, ErrorKind};
3+
use std::io::BufRead;
4+
use crate::RootStoreBuilder;
5+
6+
/// Like `Result<T,E>`, but allows for functions that can return partially complete
7+
/// work alongside an error.
8+
///
9+
/// *This type is available only if the crate is built with the "rustls" feature.*
10+
pub type PartialResult<T, E> = Result<T, (Option<T>, E)>;
11+
12+
/// Loads root certificates found in the platform's native certificate
13+
/// store.
14+
///
15+
/// On success, this returns a `rustls::RootCertStore` loaded with a
16+
/// snapshop of the root certificates found on this platform. This
17+
/// function fails in a platform-specific way, expressed in a `std::io::Error`.
18+
///
19+
/// This function can be expensive: on some platforms it involves loading
20+
/// and parsing a ~300KB disk file. It's therefore prudent to call
21+
/// this sparingly.
22+
///
23+
/// *This function is available only if the crate is built with the "rustls" feature.*
24+
pub fn load_native_certs() -> PartialResult<RootCertStore, Error> {
25+
struct RootCertStoreLoader {
26+
store: RootCertStore,
27+
};
28+
impl RootStoreBuilder for RootCertStoreLoader {
29+
fn load_der(&mut self, der: Vec<u8>) -> Result<(), Error> {
30+
self.store.add(&rustls::Certificate(der))
31+
.map_err(|err| Error::new(ErrorKind::InvalidData, err))
32+
}
33+
fn load_pem_file(&mut self, rd: &mut dyn BufRead) -> Result<(), Error> {
34+
self.store.add_pem_file(rd)
35+
.map(|_| ())
36+
.map_err(|()| Error::new(ErrorKind::InvalidData, format!("could not load PEM file")))
37+
}
38+
}
39+
let mut loader = RootCertStoreLoader {
40+
store: RootCertStore::empty(),
41+
};
42+
match crate::build_native_certs(&mut loader) {
43+
Err(err) if loader.store.is_empty() => Err((None, err)),
44+
Err(err) => Err((Some(loader.store), err)),
45+
Ok(()) => Ok(loader.store),
46+
}
47+
}

0 commit comments

Comments
 (0)