diff --git a/.clippy.toml b/.clippy.toml index b3c3a24..5e90250 100644 --- a/.clippy.toml +++ b/.clippy.toml @@ -1 +1 @@ -msrv = "1.63.0" +msrv = "1.81.0" diff --git a/.github/workflows/check.yml b/.github/workflows/check.yml index 3959b09..024c6a8 100644 --- a/.github/workflows/check.yml +++ b/.github/workflows/check.yml @@ -23,7 +23,7 @@ jobs: - nss - rust-hpke rust: - - 1.63.0 # MSRV + - 1.81.0 # MSRV - stable steps: diff --git a/Cargo.toml b/Cargo.toml index 0621518..4c318c0 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -8,3 +8,11 @@ members = [ "ohttp-client-cli", "ohttp-server", ] + +[workspace.package] +version = "0.6.0" +authors = ["Martin Thomson "] +edition = "2021" +rust-version = "1.81.0" +license = "MIT OR Apache-2.0" +repository = "https://github.com/martinthomson/ohttp" diff --git a/README.md b/README.md index 3972f29..cbddf1f 100644 --- a/README.md +++ b/README.md @@ -138,4 +138,4 @@ install itself. ## Minnimum Supported Rust Version (MSRV) -`ohttp` and `bhttp` should compile on Rust 1.63.0. +`ohttp` and `bhttp` should compile on Rust 1.81.0. diff --git a/bhttp-convert/Cargo.toml b/bhttp-convert/Cargo.toml index 58724d8..d70af3c 100644 --- a/bhttp-convert/Cargo.toml +++ b/bhttp-convert/Cargo.toml @@ -1,12 +1,16 @@ [package] name = "bhttp-convert" -version = "0.5.4" -authors = ["Martin Thomson "] -edition = "2021" +description = "Simple Tool Converting Between HTTP/1.1 and Binary HTTP" +authors.workspace = true +repository.workspace = true +version.workspace = true +edition.workspace = true +rust-version.workspace = true +license.workspace = true [dependencies] structopt = "0.3" [dependencies.bhttp] path= "../bhttp" -features = ["bhttp", "http"] +features = ["http"] diff --git a/bhttp/Cargo.toml b/bhttp/Cargo.toml index 0c0e219..ded0bee 100644 --- a/bhttp/Cargo.toml +++ b/bhttp/Cargo.toml @@ -1,21 +1,16 @@ [package] name = "bhttp" -version = "0.5.4" -authors = ["Martin Thomson "] -edition = "2021" -rust-version = "1.63.0" -license = "MIT OR Apache-2.0" -description = "Binary HTTP messages (RFC 9292)" -repository = "https://github.com/martinthomson/ohttp" +description = "Binary HTTP Messages (RFC 9292)" +authors.workspace = true +repository.workspace = true +version.workspace = true +edition.workspace = true +rust-version.workspace = true +license.workspace = true [features] -default = ["bhttp"] -bhttp = ["read-bhttp", "write-bhttp"] -http = ["read-http", "write-http"] -read-bhttp = [] -write-bhttp = [] -read-http = ["url"] -write-http = [] +default = [] +http = ["dep:url"] [dependencies] thiserror = "1" diff --git a/bhttp/src/err.rs b/bhttp/src/err.rs index d9d9b6f..b45dd43 100644 --- a/bhttp/src/err.rs +++ b/bhttp/src/err.rs @@ -31,14 +31,8 @@ pub enum Error { #[error("a message included the Upgrade field")] UpgradeUnsupported, #[error("a URL could not be parsed into components: {0}")] - #[cfg(feature = "read-http")] + #[cfg(feature = "http")] UrlParse(#[from] url::ParseError), } -#[cfg(any( - feature = "read-http", - feature = "write-http", - feature = "read-bhttp", - feature = "write-bhttp" -))] pub type Res = Result; diff --git a/bhttp/src/lib.rs b/bhttp/src/lib.rs index 3c8fbde..a728656 100644 --- a/bhttp/src/lib.rs +++ b/bhttp/src/lib.rs @@ -1,46 +1,26 @@ #![deny(warnings, clippy::pedantic)] #![allow(clippy::missing_errors_doc)] // Too lazy to document these. -#[cfg(feature = "read-bhttp")] -use std::convert::TryFrom; -#[cfg(any( - feature = "read-http", - feature = "write-http", - feature = "read-bhttp", - feature = "write-bhttp" -))] -use std::io; - -#[cfg(feature = "read-http")] +use std::{convert::TryFrom, io}; + +#[cfg(feature = "http")] use url::Url; mod err; mod parse; -#[cfg(any(feature = "read-bhttp", feature = "write-bhttp"))] mod rw; -#[cfg(any(feature = "read-http", feature = "read-bhttp",))] use std::borrow::BorrowMut; pub use err::Error; -#[cfg(any( - feature = "read-http", - feature = "write-http", - feature = "read-bhttp", - feature = "write-bhttp" -))] use err::Res; -#[cfg(feature = "read-http")] +#[cfg(feature = "http")] use parse::{downcase, is_ows, read_line, split_at, COLON, SEMICOLON, SLASH, SP}; use parse::{index_of, trim_ows, COMMA}; -#[cfg(feature = "read-bhttp")] -use rw::{read_varint, read_vec}; -#[cfg(feature = "write-bhttp")] -use rw::{write_len, write_varint, write_vec}; +use rw::{read_varint, read_vec, write_len, write_varint, write_vec}; -#[cfg(feature = "read-http")] +#[cfg(feature = "http")] const CONTENT_LENGTH: &[u8] = b"content-length"; -#[cfg(feature = "read-bhttp")] const COOKIE: &[u8] = b"cookie"; const TRANSFER_ENCODING: &[u8] = b"transfer-encoding"; const CHUNKED: &[u8] = b"chunked"; @@ -93,7 +73,6 @@ impl ReadSeek for io::Cursor where T: AsRef<[u8]> {} impl ReadSeek for io::BufReader where T: io::Read + io::Seek {} #[derive(Clone, Copy, Debug, PartialEq, Eq)] -#[cfg(any(feature = "read-bhttp", feature = "write-bhttp"))] pub enum Mode { KnownLength, IndeterminateLength, @@ -120,7 +99,7 @@ impl Field { &self.value } - #[cfg(feature = "write-http")] + #[cfg(feature = "http")] pub fn write_http(&self, w: &mut impl io::Write) -> Res<()> { w.write_all(&self.name)?; w.write_all(b": ")?; @@ -129,14 +108,13 @@ impl Field { Ok(()) } - #[cfg(feature = "write-bhttp")] pub fn write_bhttp(&self, w: &mut impl io::Write) -> Res<()> { write_vec(&self.name, w)?; write_vec(&self.value, w)?; Ok(()) } - #[cfg(feature = "read-http")] + #[cfg(feature = "http")] pub fn obs_fold(&mut self, extra: &[u8]) { self.value.push(SP); self.value.extend(trim_ows(extra)); @@ -192,7 +170,7 @@ impl FieldSection { /// As required by the HTTP specification, remove the Connection header /// field, everything it refers to, and a few extra fields. - #[cfg(feature = "read-http")] + #[cfg(feature = "http")] fn strip_connection_headers(&mut self) { const CONNECTION: &[u8] = b"connection"; const PROXY_CONNECTION: &[u8] = b"proxy-connection"; @@ -232,7 +210,7 @@ impl FieldSection { }); } - #[cfg(feature = "read-http")] + #[cfg(feature = "http")] fn parse_line(fields: &mut Vec, line: Vec) -> Res<()> { // obs-fold is helpful in specs, so support it here too let f = if is_ows(line[0]) { @@ -251,7 +229,7 @@ impl FieldSection { Ok(()) } - #[cfg(feature = "read-http")] + #[cfg(feature = "http")] pub fn read_http(r: &mut T) -> Res where T: BorrowMut + ?Sized, @@ -267,7 +245,6 @@ impl FieldSection { } } - #[cfg(feature = "read-bhttp")] fn read_bhttp_fields(terminator: bool, r: &mut T) -> Res> where T: BorrowMut + ?Sized, @@ -302,7 +279,6 @@ impl FieldSection { } } - #[cfg(feature = "read-bhttp")] pub fn read_bhttp(mode: Mode, r: &mut T) -> Res where T: BorrowMut + ?Sized, @@ -320,7 +296,6 @@ impl FieldSection { Ok(Self(fields)) } - #[cfg(feature = "write-bhttp")] fn write_bhttp_headers(&self, w: &mut impl io::Write) -> Res<()> { for f in &self.0 { f.write_bhttp(w)?; @@ -328,7 +303,6 @@ impl FieldSection { Ok(()) } - #[cfg(feature = "write-bhttp")] pub fn write_bhttp(&self, mode: Mode, w: &mut impl io::Write) -> Res<()> { if mode == Mode::KnownLength { let mut buf = Vec::new(); @@ -341,7 +315,7 @@ impl FieldSection { Ok(()) } - #[cfg(feature = "write-http")] + #[cfg(feature = "http")] pub fn write_http(&self, w: &mut impl io::Write) -> Res<()> { for f in &self.0 { f.write_http(w)?; @@ -420,7 +394,7 @@ impl ControlData { } } - #[cfg(feature = "read-http")] + #[cfg(feature = "http")] pub fn read_http(line: Vec) -> Res { // request-line = method SP request-target SP HTTP-version // status-line = HTTP-version SP status-code SP [reason-phrase] @@ -467,7 +441,6 @@ impl ControlData { } } - #[cfg(feature = "read-bhttp")] pub fn read_bhttp(request: bool, r: &mut T) -> Res where T: BorrowMut + ?Sized, @@ -493,7 +466,6 @@ impl ControlData { } /// If this is an informational response. - #[cfg(any(feature = "read-bhttp", feature = "read-http"))] #[must_use] fn informational(&self) -> Option { match self { @@ -502,7 +474,6 @@ impl ControlData { } } - #[cfg(feature = "write-bhttp")] #[must_use] fn code(&self, mode: Mode) -> u64 { match (self, mode) { @@ -513,7 +484,6 @@ impl ControlData { } } - #[cfg(feature = "write-bhttp")] pub fn write_bhttp(&self, w: &mut impl io::Write) -> Res<()> { match self { Self::Request { @@ -532,7 +502,7 @@ impl ControlData { Ok(()) } - #[cfg(feature = "write-http")] + #[cfg(feature = "http")] pub fn write_http(&self, w: &mut impl io::Write) -> Res<()> { match self { Self::Request { @@ -581,7 +551,6 @@ impl InformationalResponse { &self.fields } - #[cfg(feature = "write-bhttp")] fn write_bhttp(&self, mode: Mode, w: &mut impl io::Write) -> Res<()> { write_varint(self.status.code(), w)?; self.fields.write_bhttp(mode, w)?; @@ -662,7 +631,7 @@ impl Message { &self.trailer } - #[cfg(feature = "read-http")] + #[cfg(feature = "http")] fn read_chunked(r: &mut T) -> Res> where T: BorrowMut + ?Sized, @@ -686,8 +655,7 @@ impl Message { } } - #[cfg(feature = "read-http")] - #[allow(clippy::read_zero_byte_vec)] // https://github.com/rust-lang/rust-clippy/issues/9274 + #[cfg(feature = "http")] pub fn read_http(r: &mut T) -> Res where T: BorrowMut + ?Sized, @@ -741,7 +709,7 @@ impl Message { }) } - #[cfg(feature = "write-http")] + #[cfg(feature = "http")] pub fn write_http(&self, w: &mut impl io::Write) -> Res<()> { for info in &self.informational { ControlData::Response(info.status()).write_http(w)?; @@ -770,7 +738,6 @@ impl Message { } /// Read a BHTTP message. - #[cfg(feature = "read-bhttp")] pub fn read_bhttp(r: &mut T) -> Res where T: BorrowMut + ?Sized, @@ -815,7 +782,6 @@ impl Message { }) } - #[cfg(feature = "write-bhttp")] pub fn write_bhttp(&self, mode: Mode, w: &mut impl io::Write) -> Res<()> { write_varint(self.control.code(mode), w)?; for info in &self.informational { @@ -833,7 +799,7 @@ impl Message { } } -#[cfg(feature = "write-http")] +#[cfg(feature = "http")] impl std::fmt::Debug for Message { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> Result<(), std::fmt::Error> { let mut buf = Vec::new(); diff --git a/bhttp/src/parse.rs b/bhttp/src/parse.rs index ee52493..06165fc 100644 --- a/bhttp/src/parse.rs +++ b/bhttp/src/parse.rs @@ -1,20 +1,21 @@ -#[cfg(feature = "read-http")] -use crate::{Error, ReadSeek, Res}; -#[cfg(feature = "read-http")] +#[cfg(feature = "http")] use std::borrow::BorrowMut; +#[cfg(feature = "http")] +use crate::{Error, ReadSeek, Res}; + pub const HTAB: u8 = 0x09; -#[cfg(feature = "read-http")] +#[cfg(feature = "http")] pub const NL: u8 = 0x0a; -#[cfg(feature = "read-http")] +#[cfg(feature = "http")] pub const CR: u8 = 0x0d; pub const SP: u8 = 0x20; pub const COMMA: u8 = 0x2c; -#[cfg(feature = "read-http")] +#[cfg(feature = "http")] pub const SLASH: u8 = 0x2f; -#[cfg(feature = "read-http")] +#[cfg(feature = "http")] pub const COLON: u8 = 0x3a; -#[cfg(feature = "read-http")] +#[cfg(feature = "http")] pub const SEMICOLON: u8 = 0x3b; pub fn is_ows(x: u8) -> bool { @@ -34,7 +35,7 @@ pub fn trim_ows(v: &[u8]) -> &[u8] { &v[..0] } -#[cfg(feature = "read-http")] +#[cfg(feature = "http")] pub fn downcase(n: &mut [u8]) { for i in n { if *i >= 0x41 && *i <= 0x5a { @@ -52,7 +53,7 @@ pub fn index_of(v: u8, line: &[u8]) -> Option { None } -#[cfg(feature = "read-http")] +#[cfg(feature = "http")] pub fn split_at(v: u8, mut line: Vec) -> Option<(Vec, Vec)> { index_of(v, &line).map(|i| { let tail = line.split_off(i + 1); @@ -61,7 +62,7 @@ pub fn split_at(v: u8, mut line: Vec) -> Option<(Vec, Vec)> { }) } -#[cfg(feature = "read-http")] +#[cfg(feature = "http")] pub fn read_line(r: &mut T) -> Res> where T: BorrowMut + ?Sized, diff --git a/bhttp/src/rw.rs b/bhttp/src/rw.rs index 5e93534..58abe41 100644 --- a/bhttp/src/rw.rs +++ b/bhttp/src/rw.rs @@ -1,12 +1,10 @@ -#[cfg(feature = "read-bhttp")] -use std::borrow::BorrowMut; -use std::{convert::TryFrom, io}; +use std::{borrow::BorrowMut, convert::TryFrom, io}; -use crate::err::Res; -#[cfg(feature = "read-bhttp")] -use crate::{err::Error, ReadSeek}; +use crate::{ + err::{Error, Res}, + ReadSeek, +}; -#[cfg(feature = "write-bhttp")] #[allow(clippy::cast_possible_truncation)] pub(crate) fn write_uint(v: impl Into, w: &mut impl io::Write) -> Res<()> { let v = v.into().to_be_bytes(); @@ -15,7 +13,6 @@ pub(crate) fn write_uint(v: impl Into, w: &mut impl io::Wri Ok(()) } -#[cfg(feature = "write-bhttp")] pub fn write_varint(v: impl Into, w: &mut impl io::Write) -> Res<()> { let v = v.into(); match () { @@ -27,19 +24,16 @@ pub fn write_varint(v: impl Into, w: &mut impl io::Write) -> Res<()> { } } -#[cfg(feature = "write-bhttp")] pub fn write_len(len: usize, w: &mut impl io::Write) -> Res<()> { write_varint(u64::try_from(len).unwrap(), w) } -#[cfg(feature = "write-bhttp")] pub fn write_vec(v: &[u8], w: &mut impl io::Write) -> Res<()> { write_len(v.len(), w)?; w.write_all(v)?; Ok(()) } -#[cfg(feature = "read-bhttp")] fn read_uint(n: usize, r: &mut T) -> Res> where T: BorrowMut + ?Sized, @@ -60,7 +54,6 @@ where } } -#[cfg(feature = "read-bhttp")] pub fn read_varint(r: &mut T) -> Res> where T: BorrowMut + ?Sized, @@ -79,7 +72,6 @@ where } } -#[cfg(feature = "read-bhttp")] pub fn read_vec(r: &mut T) -> Res>> where T: BorrowMut + ?Sized, diff --git a/bhttp/tests/test.rs b/bhttp/tests/test.rs index c6729c6..9ed9731 100644 --- a/bhttp/tests/test.rs +++ b/bhttp/tests/test.rs @@ -1,5 +1,5 @@ // Rather than grapple with #[cfg(...)] for every variable and import. -#![cfg(all(feature = "http", feature = "bhttp"))] +#![cfg(feature = "http")] use std::{io::Cursor, mem::drop}; diff --git a/ohttp-client-cli/Cargo.toml b/ohttp-client-cli/Cargo.toml index a2b63a6..32ce269 100644 --- a/ohttp-client-cli/Cargo.toml +++ b/ohttp-client-cli/Cargo.toml @@ -1,8 +1,12 @@ [package] name = "ohttp-client-cli" -version = "0.5.4" -authors = ["Martin Thomson "] -edition = "2021" +description = "Crude CLI Client for OHTTP" +authors.workspace = true +repository.workspace = true +version.workspace = true +edition.workspace = true +rust-version.workspace = true +license.workspace = true [features] default = ["rust-hpke"] @@ -15,7 +19,7 @@ hex = "0.4" [dependencies.bhttp] path= "../bhttp" -features = ["bhttp", "http"] +features = ["http"] [dependencies.ohttp] path= "../ohttp" diff --git a/ohttp-client/Cargo.toml b/ohttp-client/Cargo.toml index bd994a7..4841da6 100644 --- a/ohttp-client/Cargo.toml +++ b/ohttp-client/Cargo.toml @@ -1,8 +1,12 @@ [package] name = "ohttp-client" -version = "0.5.4" -authors = ["Martin Thomson "] -edition = "2021" +description = "Sample Client for OHTTP" +authors.workspace = true +repository.workspace = true +version.workspace = true +edition.workspace = true +rust-version.workspace = true +license.workspace = true [features] default = ["rust-hpke"] @@ -19,7 +23,7 @@ tokio = { version = "1", features = ["full"] } [dependencies.bhttp] path= "../bhttp" -features = ["bhttp", "http"] +features = ["http"] [dependencies.ohttp] path= "../ohttp" diff --git a/ohttp-server/Cargo.toml b/ohttp-server/Cargo.toml index a7dc185..62f2017 100644 --- a/ohttp-server/Cargo.toml +++ b/ohttp-server/Cargo.toml @@ -1,8 +1,12 @@ [package] name = "ohttp-server" -version = "0.5.4" -authors = ["Martin Thomson "] -edition = "2021" +description = "Simple Test Server for OHTTP" +authors.workspace = true +repository.workspace = true +version.workspace = true +edition.workspace = true +rust-version.workspace = true +license.workspace = true [features] default = ["rust-hpke"] @@ -18,7 +22,7 @@ warp = { version = "0.3", features = ["tls"] } [dependencies.bhttp] path= "../bhttp" -features = ["bhttp", "write-http"] +features = ["http"] [dependencies.ohttp] path= "../ohttp" diff --git a/ohttp/Cargo.toml b/ohttp/Cargo.toml index 1d9de6c..695b3a2 100644 --- a/ohttp/Cargo.toml +++ b/ohttp/Cargo.toml @@ -1,24 +1,24 @@ [package] name = "ohttp" -version = "0.5.4" -authors = ["Martin Thomson "] -edition = "2021" -rust-version = "1.63.0" +description = "Oblivious HTTP (RFC 9458)" build = "build.rs" -license = "MIT OR Apache-2.0" -description = "Oblivious HTTP" -repository = "https://github.com/martinthomson/ohttp" +authors.workspace = true +repository.workspace = true +version.workspace = true +edition.workspace = true +rust-version.workspace = true +license.workspace = true [features] default = ["client", "server", "rust-hpke"] app-svc = ["nss"] client = [] external-sqlite = [] -gecko = ["nss", "mozbuild"] -nss = ["bindgen", "regex-mess"] -pq = ["hpke-pq"] -regex-mess = ["regex", "regex-automata", "regex-syntax"] -rust-hpke = ["rand", "aead", "aes-gcm", "chacha20poly1305", "hkdf", "sha2", "hpke"] +gecko = ["nss", "dep:mozbuild"] +nss = ["dep:bindgen", "regex-mess"] +pq = ["dep:hpke-pq"] +regex-mess = ["dep:regex", "dep:regex-automata", "dep:regex-syntax"] +rust-hpke = ["dep:rand", "dep:aead", "dep:aes-gcm", "dep:chacha20poly1305", "dep:hkdf", "dep:sha2", "dep:hpke"] server = [] [dependencies] @@ -29,7 +29,6 @@ chacha20poly1305 = {version = "0.8", optional = true} hex = "0.4" hkdf = {version = "0.11", optional = true} hpke = {version = "0.11.0", optional = true, default-features = false, features = ["std", "x25519"]} -lazy_static = "1.4" log = {version = "0.4", default-features = false} rand = {version = "0.8", optional = true} # bindgen uses regex and friends, which have been updated past our MSRV diff --git a/ohttp/src/nss/aead.rs b/ohttp/src/nss/aead.rs index 18f0b66..84720fc 100644 --- a/ohttp/src/nss/aead.rs +++ b/ohttp/src/nss/aead.rs @@ -1,3 +1,11 @@ +use std::{ + convert::{TryFrom, TryInto}, + mem, + os::raw::c_int, +}; + +use log::trace; + use super::{ err::secstatus_to_res, p11::{ @@ -13,12 +21,6 @@ use crate::{ err::{Error, Res}, hpke::Aead as AeadId, }; -use log::trace; -use std::{ - convert::{TryFrom, TryInto}, - mem, - os::raw::c_int, -}; /// All the nonces are the same length. Exploit that. pub const NONCE_LEN: usize = 12; @@ -177,8 +179,8 @@ impl Aead { c_int_len(aad.len()), pt.as_mut_ptr(), &mut pt_len, - c_int_len(pt.len()), // signed :( - ct.as_ptr().add(pt_expected) as *mut _, // const cast :( + c_int_len(pt.len()), // signed :( + ct.as_ptr().add(pt_expected).cast_mut(), // const cast :( c_int_len(TAG_LEN), ct.as_ptr(), c_int_len(pt_expected), diff --git a/ohttp/src/nss/hkdf.rs b/ohttp/src/nss/hkdf.rs index 470b1dd..835a034 100644 --- a/ohttp/src/nss/hkdf.rs +++ b/ohttp/src/nss/hkdf.rs @@ -1,3 +1,7 @@ +use std::{convert::TryFrom, os::raw::c_int, ptr::null_mut}; + +use log::trace; + use super::{ super::hpke::{Aead, Kdf}, p11::{ @@ -10,8 +14,6 @@ use super::{ }, }; use crate::err::Res; -use log::trace; -use std::{convert::TryFrom, os::raw::c_int, ptr::null_mut}; #[derive(Clone, Copy)] pub enum KeyMechanism { @@ -80,7 +82,7 @@ impl Hkdf { bExpand: CK_BBOOL::from(false), prfHashMechanism: self.mech(), ulSaltType: CK_ULONG::from(salt_type), - pSalt: salt.as_ptr() as *mut _, // const-cast = bad API + pSalt: salt.as_ptr().cast_mut(), // const-cast = bad API ulSaltLen: CK_ULONG::try_from(salt.len()).unwrap(), hSaltKey: CK_OBJECT_HANDLE::from(CK_INVALID_HANDLE), pInfo: null_mut(), @@ -118,7 +120,7 @@ impl Hkdf { pSalt: null_mut(), ulSaltLen: 0, hSaltKey: CK_OBJECT_HANDLE::from(CK_INVALID_HANDLE), - pInfo: info.as_ptr() as *mut _, // const-cast = bad API + pInfo: info.as_ptr().cast_mut(), // const-cast = bad API ulInfoLen: CK_ULONG::try_from(info.len()).unwrap(), } } diff --git a/ohttp/src/nss/mod.rs b/ohttp/src/nss/mod.rs index 1b60c9e..9aa3257 100644 --- a/ohttp/src/nss/mod.rs +++ b/ohttp/src/nss/mod.rs @@ -11,11 +11,12 @@ pub mod aead; pub mod hkdf; pub mod hpke; -pub use self::p11::{random, PrivateKey, PublicKey}; +use std::{ptr::null, sync::OnceLock}; + use err::secstatus_to_res; pub use err::Error; -use lazy_static::lazy_static; -use std::ptr::null; + +pub use self::p11::{random, PrivateKey, PublicKey}; #[allow(clippy::pedantic, non_upper_case_globals, clippy::upper_case_acronyms)] mod nss_init { @@ -29,39 +30,37 @@ const SECSuccess: SECStatus = nss_init::_SECStatus_SECSuccess; #[allow(non_upper_case_globals)] const SECFailure: SECStatus = nss_init::_SECStatus_SECFailure; -#[derive(PartialEq, Eq)] -enum NssLoaded { - External, - NoDb, +fn already_initialized() -> bool { + unsafe { nss_init::NSS_IsInitialized() != 0 } } -impl Drop for NssLoaded { - fn drop(&mut self) { - if matches!(self, Self::NoDb) { - unsafe { - secstatus_to_res(nss_init::NSS_Shutdown()).expect("NSS Shutdown failed"); +/// Initialize NSS. This only executes the initialization routines once. +pub fn init() { + #[derive(PartialEq, Eq)] + enum NssLoaded { + External, + Loaded, + } + + impl Drop for NssLoaded { + fn drop(&mut self) { + if matches!(self, Self::Loaded) { + unsafe { + secstatus_to_res(nss_init::NSS_Shutdown()).expect("NSS Shutdown failed"); + } } } } -} -lazy_static! { - static ref INITIALIZED: NssLoaded = { + static INITIALIZED: OnceLock = OnceLock::new(); + + INITIALIZED.get_or_init(|| { if already_initialized() { - return NssLoaded::External; + NssLoaded::External + } else { + secstatus_to_res(unsafe { nss_init::NSS_NoDB_Init(null()) }) + .expect("NSS_NoDB_Init failed"); + NssLoaded::Loaded } - - secstatus_to_res(unsafe { nss_init::NSS_NoDB_Init(null()) }).expect("NSS_NoDB_Init failed"); - - NssLoaded::NoDb - }; -} - -fn already_initialized() -> bool { - unsafe { nss_init::NSS_IsInitialized() != 0 } -} - -/// Initialize NSS. This only executes the initialization routines once. -pub fn init() { - lazy_static::initialize(&INITIALIZED); + }); } diff --git a/ohttp/src/nss/p11.rs b/ohttp/src/nss/p11.rs index 9bddef6..af0ab58 100644 --- a/ohttp/src/nss/p11.rs +++ b/ohttp/src/nss/p11.rs @@ -4,8 +4,6 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -use super::err::{secstatus_to_res, Error}; -use crate::err::Res; use std::{ convert::TryFrom, marker::PhantomData, @@ -14,6 +12,9 @@ use std::{ ptr::null_mut, }; +use super::err::{secstatus_to_res, Error}; +use crate::err::Res; + #[allow( clippy::pedantic, clippy::upper_case_acronyms, @@ -235,7 +236,7 @@ impl<'a, T: Sized + 'a> ParamItem<'a, T> { pub fn new(v: &'a mut T) -> Self { let item = SECItem { type_: SECItemType::siBuffer, - data: (v as *mut T).cast::(), + data: std::ptr::from_mut(v).cast::(), len: c_uint::try_from(mem::size_of::()).unwrap(), }; Self { @@ -261,7 +262,7 @@ impl Item { pub(crate) fn wrap(buf: &[u8]) -> SECItem { SECItem { type_: SECItemType::siBuffer, - data: buf.as_ptr() as *mut u8, + data: buf.as_ptr().cast_mut(), len: c_uint::try_from(buf.len()).unwrap(), } } diff --git a/pre-commit b/pre-commit index 758b923..8b5debd 100755 --- a/pre-commit +++ b/pre-commit @@ -1,9 +1,12 @@ #!/usr/bin/env bash -# This is a pre-commit hook that validates code formatting. +# This is a pre-commit hook that validates code. # # Install this by running the script with an argument of "install", # which installs a symlink to .git/hooks/precommit: # $ ln -s ../../hooks/pre-commit .git/hooks/pre-commit +# +# Run "./pre-commit all" to have this run a more complete set of tests +# over the current tree. root="$(git rev-parse --show-toplevel 2>/dev/null)" @@ -25,9 +28,11 @@ fi # Check formatting. if [[ "$1" != "all" ]]; then - msg="pre-commit stash @$(git rev-parse --short @) $RANDOM" - trap 'git stash list -1 --format="format:%s" | grep -q "'"$msg"'" && git stash pop -q' EXIT - git stash push -k -u -q -m "$msg" + dotgit="$(git rev-parse --git-dir)" + msg="pre-commit stash @$(git rev-parse --short @) $$-$RANDOM" + trap 'git stash list -1 --format="format:%s" | grep -q "'"$msg"'" && git stash pop -q && mv "'"$root"'"/MERGE_* "'"$dotgit"'"' EXIT + mv "$dotgit"/MERGE_* "$root" + git stash push -kuq -m "$msg" fi if ! errors=($(cargo fmt -- --check --config imports_granularity=crate -l)); then echo "Formatting errors found." @@ -37,17 +42,22 @@ if ! errors=($(cargo fmt -- --check --config imports_granularity=crate -l)); the done exit 1 fi -if ! cargo clippy --tests; then - exit 1 -fi -if ! cargo test; then - exit 1 +versions=(stable) +if [[ "$1" == "all" ]]; then + versions+=(1.81.0) fi -if [[ -n "$NSS_DIR" ]]; then - if ! cargo clippy --tests --no-default-features --features nss; then +check() { + if ! "$@"; then + echo "Failed [$?]: ${@@Q}" exit 1 fi - if ! cargo test --no-default-features --features nss; then - exit 1 +} + +for v in "${versions[@]}"; do + check cargo "+$v" clippy --tests + check cargo "+$v" test + if [[ -n "$NSS_DIR" ]]; then + check cargo "+$v" clippy --tests --no-default-features --features nss,http + check cargo "+$v" test --no-default-features --features nss,http fi -fi +done