diff --git a/.github/workflows/build_and_test.yml b/.github/workflows/build_and_test.yml
new file mode 100644
index 0000000..22fdd5c
--- /dev/null
+++ b/.github/workflows/build_and_test.yml
@@ -0,0 +1,54 @@
+name: Build, Test, Publish Coverage
+
+on:
+ push:
+ branches: ["main"]
+ pull_request:
+ branches: ["main", "dev"]
+
+env:
+ CARGO_TERM_COLOR: always
+
+jobs:
+ linux:
+ runs-on: ubuntu-latest
+
+ steps:
+ - uses: actions/checkout@v4
+ - uses: Swatinem/rust-cache@v2
+ with:
+ cache-all-crates: "true"
+ prefix-key: "linux"
+ - name: Build, Test and Publish Coverage
+ run: |
+ if [ -n "${{ secrets.COVERALLS_REPO_TOKEN }}" ]; then
+ curl -L --proto '=https' --tlsv1.2 -sSf https://raw.githubusercontent.com/cargo-bins/cargo-binstall/main/install-from-binstall-release.sh | bash
+ cargo binstall --no-confirm cargo-tarpaulin --force
+ cargo tarpaulin --all-features --avoid-cfg-tarpaulin --tests --examples --verbose --skip-clean --coveralls ${{ secrets.COVERALLS_REPO_TOKEN }} --timeout 120
+ else
+ echo "Code Coverage step is skipped on forks!"
+ cargo build --verbose --all-features
+ cargo test --verbose --all-features --tests --examples
+ fi
+ wasm:
+ runs-on: macos-latest
+ steps:
+ - uses: actions/checkout@v4
+ - uses: Swatinem/rust-cache@v2
+ with:
+ cache-all-crates: "true"
+ prefix-key: "macos"
+ - name: Run WASM tests with Safari, Firefox, Chrome
+ run: |
+ rustup target add wasm32-unknown-unknown
+ curl -L --proto '=https' --tlsv1.2 -sSf https://raw.githubusercontent.com/cargo-bins/cargo-binstall/main/install-from-binstall-release.sh | bash
+ cargo binstall --no-confirm wasm-bindgen-cli --version "0.2.88" --force
+ cargo binstall --no-confirm wasm-pack --force
+ wasm-pack test --node -- --features wasm --examples
+ wasm-pack test --firefox -- --features wasm --examples
+ wasm-pack test --chrome -- --features wasm --examples
+ wasm-pack test --safari -- --features wasm --examples
+ wasm-pack test --node -- --features wasm
+ wasm-pack test --firefox -- --features wasm
+ wasm-pack test --chrome -- --features wasm
+ wasm-pack test --safari -- --features wasm
diff --git a/Cargo.toml b/Cargo.toml
index 10d0ac9..c800c5b 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -9,8 +9,12 @@ repository = "https://github.com/polyphony-chat/polyproto"
[lib]
crate-type = ["rlib", "cdylib", "staticlib"]
+[features]
+wasm = ["dep:getrandom", "getrandom/js"]
+
[dependencies]
der = { version = "0.7.8", features = ["pem"] }
+getrandom = { version = "0.2.12", optional = true }
spki = "0.7.3"
thiserror = "1.0.57"
x509-cert = { version = "0.2.5", default-features = false }
@@ -19,3 +23,7 @@ x509-cert = { version = "0.2.5", default-features = false }
ed25519-dalek = { version = "2.1.1", features = ["rand_core", "signature"] }
rand = "0.8.5"
polyproto = { path = "./" }
+
+[target.'cfg(target_arch = "wasm32")'.dev-dependencies]
+wasm-bindgen-test = "0.3.39"
+wasm-bindgen = "0.2.89"
diff --git a/README.md b/README.md
index 628eab0..0178ee7 100644
--- a/README.md
+++ b/README.md
@@ -1,6 +1,16 @@
+
+
+[![Discord]][Discord-invite]
+[![Matrix]][Matrix-invite]
+[![Build][build-shield]][build-url]
+[![Coverage][coverage-shield]][coverage-url]
+
+
+
+
# polyproto
-(Generic) Rust types and traits to quickly get a
+Crate supplying (generic) Rust types and traits to quickly get a
[polyproto](https://docs.polyphony.chat/Protocol%20Specifications/core/) implementation up and
running.
@@ -21,9 +31,21 @@ choice. Popular crates for cryptography and signature algorithms supply their ow
You can then use the [crate::certs] types to build certificates using your implementations of the
aforementioned traits.
+View the [examples](./examples/) directory for a simple example on how to implement and use this
+crate.
+
## Cryptography
This crate provides no cryptographic functionality whatsoever; its sole purpose is to aid in
implementing polyproto by transforming the
[polyproto specification](https://docs.polyphony.chat/Protocol%20Specifications/core/) into
well-defined yet adaptable Rust types.
+
+[build-shield]: https://img.shields.io/github/actions/workflow/status/polyphony-chat/polyproto/build_and_test.yml?style=flat
+[build-url]: https://github.com/polyphony-chat/polyproto/blob/main/.github/workflows/build_and_test.yml
+[coverage-shield]: https://coveralls.io/repos/github/polyphony-chat/polyproto/badge.svg?branch=main
+[coverage-url]: https://coveralls.io/github/polyphony-chat/polyproto?branch=main
+[Discord]: https://dcbadge.vercel.app/api/server/m3FpcapGDD?style=flat
+[Discord-invite]: https://discord.com/invite/m3FpcapGDD
+[Matrix]: https://img.shields.io/matrix/polyproto%3Atu-dresden.de?server_fqdn=matrix.tu-dresden.de&style=flat&label=Matrix%20Room
+[Matrix-invite]: https://matrix.to/#/#polyproto:tu-dresden.de
\ No newline at end of file
diff --git a/examples/ed25519_basic.rs b/examples/ed25519_basic.rs
index 7d5a60c..ede19c9 100644
--- a/examples/ed25519_basic.rs
+++ b/examples/ed25519_basic.rs
@@ -17,6 +17,7 @@ use rand::rngs::OsRng;
use spki::{AlgorithmIdentifierOwned, ObjectIdentifier, SignatureBitStringEncoding};
use thiserror::Error;
+#[cfg_attr(target_arch = "wasm32", wasm_bindgen_test::wasm_bindgen_test)]
fn main() {
let mut csprng = rand::rngs::OsRng;
// Generate a key pair
diff --git a/examples/ed25519_csr.rs b/examples/ed25519_csr.rs
index 0d709d7..2b666dd 100644
--- a/examples/ed25519_csr.rs
+++ b/examples/ed25519_csr.rs
@@ -27,6 +27,7 @@ use x509_cert::request::CertReq;
/// openssl req -in cert.csr -verify
/// ```
+#[cfg_attr(target_arch = "wasm32", wasm_bindgen_test::wasm_bindgen_test)]
fn main() {
let mut csprng = rand::rngs::OsRng;
let priv_key = Ed25519PrivateKey::gen_keypair(&mut csprng);
@@ -45,6 +46,7 @@ fn main() {
println!("Certrequest der bytes: {:?}", certrequest.to_der().unwrap());
let data = certrequest.to_der().unwrap();
let file_name_with_extension = "cert.csr";
+ #[cfg(not(target_arch = "wasm32"))]
std::fs::write(file_name_with_extension, &data).unwrap();
// TODO: The attributes are still missing. CA Certificates and Actor Certificates should have
diff --git a/src/lib.rs b/src/lib.rs
index af7ada7..54d2b96 100644
--- a/src/lib.rs
+++ b/src/lib.rs
@@ -155,7 +155,8 @@ mod test {
}
}
- #[test]
+ #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test::wasm_bindgen_test)]
+ #[cfg_attr(not(target_arch = "wasm32"), test)]
fn test_convert_serial_number() {
let biguint = Uint::new(&[10u8, 240u8]).unwrap();
assert_eq!(biguint.as_bytes(), &[10u8, 240u8]);
diff --git a/src/value_constraints.rs b/src/value_constraints.rs
index 5204a47..50e36a5 100644
--- a/src/value_constraints.rs
+++ b/src/value_constraints.rs
@@ -109,7 +109,8 @@ mod name_constraints {
use crate::Constrained;
- #[test]
+ #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test::wasm_bindgen_test)]
+ #[cfg_attr(not(target_arch = "wasm32"), test)]
fn correct() {
let name = Name::from_str(
"cn=flori,dc=localhost,uid=h3g2jt4dhfgj8hjs,uniqueIdentifier=flori@localhost",
@@ -120,19 +121,22 @@ mod name_constraints {
name.validate().unwrap();
}
- #[test]
+ #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test::wasm_bindgen_test)]
+ #[cfg_attr(not(target_arch = "wasm32"), test)]
fn no_domain_component() {
let name = Name::from_str("CN=flori").unwrap();
assert!(name.validate().is_err());
}
- #[test]
+ #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test::wasm_bindgen_test)]
+ #[cfg_attr(not(target_arch = "wasm32"), test)]
fn two_cns() {
let name = Name::from_str("CN=flori,CN=xenia,DC=localhost").unwrap();
assert!(name.validate().is_err())
}
- #[test]
+ #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test::wasm_bindgen_test)]
+ #[cfg_attr(not(target_arch = "wasm32"), test)]
fn two_uid_or_uniqueid() {
let name = Name::from_str("CN=flori,CN=xenia,uid=numbaone,uid=numbatwo").unwrap();
assert!(name.validate().is_err());
@@ -142,7 +146,8 @@ mod name_constraints {
assert!(name.validate().is_err())
}
- #[test]
+ #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test::wasm_bindgen_test)]
+ #[cfg_attr(not(target_arch = "wasm32"), test)]
fn uid_and_no_uniqueid_or_uniqueid_and_no_uid() {
let name = Name::from_str("CN=flori,CN=xenia,uid=numbaone").unwrap();
assert!(name.validate().is_err());
@@ -157,17 +162,20 @@ mod session_id_constraints {
use crate::certs::SessionId;
- #[test]
+ #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test::wasm_bindgen_test)]
+ #[cfg_attr(not(target_arch = "wasm32"), test)]
fn zero_long_session_id_fails() {
assert!(SessionId::new(Ia5String::new("").unwrap()).is_err())
}
- #[test]
+ #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test::wasm_bindgen_test)]
+ #[cfg_attr(not(target_arch = "wasm32"), test)]
fn thirtytwo_length_session_id_is_ok() {
assert!(SessionId::new(Ia5String::new("11111111111111111111111111222222").unwrap()).is_ok())
}
- #[test]
+ #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test::wasm_bindgen_test)]
+ #[cfg_attr(not(target_arch = "wasm32"), test)]
fn thirtythree_length_session_id_fails() {
assert!(
SessionId::new(Ia5String::new("111111111111111111111111112222223").unwrap()).is_err()