Skip to content

Commit b9800b7

Browse files
msvbgtirithen
andauthored
feat(serde): ser./deser. Path and Paths
Add serde derive Serialize/Deserialize when serde feature is active. --------- Co-authored-by: Fredrik Söderström <tirithen@gmail.com>
1 parent b1c6386 commit b9800b7

File tree

6 files changed

+129
-12
lines changed

6 files changed

+129
-12
lines changed

.github/workflows/test.yml

Lines changed: 18 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,14 +4,30 @@ on:
44
pull_request:
55

66
jobs:
7-
test:
8-
name: cargo test
7+
test_all_features:
8+
name: cargo test (all features)
99
runs-on: ubuntu-latest
1010
steps:
1111
- uses: actions/checkout@v3
1212
- uses: actions-rust-lang/setup-rust-toolchain@v1
1313
- run: cargo test --all-features
1414

15+
test_no_features:
16+
name: cargo test (no features)
17+
runs-on: ubuntu-latest
18+
steps:
19+
- uses: actions/checkout@v3
20+
- uses: actions-rust-lang/setup-rust-toolchain@v1
21+
- run: cargo test
22+
23+
test_serde_feature:
24+
name: cargo test (serde)
25+
runs-on: ubuntu-latest
26+
steps:
27+
- uses: actions/checkout@v3
28+
- uses: actions-rust-lang/setup-rust-toolchain@v1
29+
- run: cargo test --features serde
30+
1531
# Check formatting with rustfmt
1632
formatting:
1733
name: cargo fmt

Cargo.lock

Lines changed: 48 additions & 2 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Cargo.toml

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,15 +14,18 @@ categories = ["algorithms"]
1414
[features]
1515
default = ["doc-images"]
1616
doc-images = []
17+
serde = ["dep:serde", "clipper2c-sys/serde"]
1718

1819
[dependencies]
1920
libc = "0.2"
20-
clipper2c-sys = "0.1.1"
21+
clipper2c-sys = "0.1.2"
2122
thiserror = "1.0.59"
23+
serde = { version = "1", features = ["derive"], optional = true }
2224

2325
[dev-dependencies]
2426
macroquad = "0.4.5"
2527
embed-doc-image = "0.1"
28+
serde_json = "1"
2629

2730
[package.metadata.docs.rs]
2831
# docs.rs uses a nightly compiler, so by instructing it to use our `doc-images` feature we

src/path.rs

Lines changed: 17 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,12 @@ use crate::{
1919
/// let path_from_tuples: Path = vec![(0.0, 0.0), (5.0, 0.0), (5.0, 6.0), (0.0, 6.0)].into();
2020
/// let path_from_slices: Path = vec![[0.0, 0.0], [5.0, 0.0], [5.0, 6.0], [0.0, 6.0]].into();
2121
/// ```
22-
#[derive(Debug, Clone, Default)]
22+
#[derive(Debug, Clone, Default, PartialEq)]
23+
#[cfg_attr(
24+
feature = "serde",
25+
derive(serde::Serialize, serde::Deserialize),
26+
serde(bound = "P: PointScaler")
27+
)]
2328
pub struct Path<P: PointScaler = Centi>(Vec<Point<P>>);
2429

2530
impl<P: PointScaler> Path<P> {
@@ -421,4 +426,15 @@ mod test {
421426
let area = path.signed_area();
422427
assert_eq!(area, -1200.0);
423428
}
429+
430+
#[cfg(feature = "serde")]
431+
#[test]
432+
fn test_serde() {
433+
let path = Path::<Centi>::from(vec![(0.0, 0.0), (1.0, 1.0)]);
434+
let serialized = serde_json::to_string(&path).unwrap();
435+
assert_eq!(serialized, r#"[{"x":0,"y":0},{"x":100,"y":100}]"#);
436+
437+
let deserialized: Path<Centi> = serde_json::from_str(&serialized).unwrap();
438+
assert_eq!(deserialized, path);
439+
}
424440
}

src/paths.rs

Lines changed: 17 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,12 @@ use crate::{
1919
/// let paths_from_single_vec: Paths = vec![(0.0, 0.0), (5.0, 0.0), (5.0, 6.0), (0.0, 6.0)].into();
2020
/// let paths_from_vec_of_vecs: Paths = vec![vec![(0.0, 0.0), (5.0, 0.0), (5.0, 6.0), (0.0, 6.0)]].into();
2121
/// ```
22-
#[derive(Debug, Clone, Default)]
22+
#[derive(Debug, Clone, Default, PartialEq)]
23+
#[cfg_attr(
24+
feature = "serde",
25+
derive(serde::Serialize, serde::Deserialize),
26+
serde(bound = "P: PointScaler")
27+
)]
2328
pub struct Paths<P: PointScaler = Centi>(Vec<Path<P>>);
2429

2530
impl<P: PointScaler> Paths<P> {
@@ -453,4 +458,15 @@ mod test {
453458
let area = paths.signed_area();
454459
assert_eq!(area, 6000.0);
455460
}
461+
462+
#[cfg(feature = "serde")]
463+
#[test]
464+
fn test_serde() {
465+
let paths = Paths::<Centi>::from(vec![(0.4, 0.0), (5.0, 1.0)]);
466+
let serialized = serde_json::to_string(&paths).unwrap();
467+
assert_eq!(serialized, r#"[[{"x":40,"y":0},{"x":500,"y":100}]]"#);
468+
469+
let deserialized: Paths<Centi> = serde_json::from_str(&serialized).unwrap();
470+
assert_eq!(deserialized, paths);
471+
}
456472
}

src/point.rs

Lines changed: 25 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -25,31 +25,31 @@ pub trait PointScaler: Clone + Copy {
2525
}
2626

2727
/// No scaling.
28-
#[derive(Debug, Copy, Clone)]
28+
#[derive(Debug, Copy, Clone, PartialEq)]
2929
pub struct One;
3030

3131
impl PointScaler for One {
3232
const MULTIPLIER: f64 = 1.0;
3333
}
3434

3535
/// Scale by 10.
36-
#[derive(Debug, Copy, Clone)]
36+
#[derive(Debug, Copy, Clone, PartialEq)]
3737
pub struct Deci;
3838

3939
impl PointScaler for Deci {
4040
const MULTIPLIER: f64 = 10.0;
4141
}
4242

4343
/// Scale by 100. This is the default.
44-
#[derive(Debug, Copy, Clone)]
44+
#[derive(Debug, Copy, Clone, PartialEq)]
4545
pub struct Centi;
4646

4747
impl PointScaler for Centi {
4848
const MULTIPLIER: f64 = 100.0;
4949
}
5050

5151
/// Scale by 1000.
52-
#[derive(Debug, Copy, Clone)]
52+
#[derive(Debug, Copy, Clone, PartialEq)]
5353
pub struct Milli;
5454

5555
impl PointScaler for Milli {
@@ -85,7 +85,16 @@ impl PointScaler for Milli {
8585
/// assert_eq!(point.y_scaled(), 2000);
8686
/// ```
8787
#[derive(Debug, Copy, Clone)]
88-
pub struct Point<P: PointScaler = Centi>(ClipperPoint64, PhantomData<P>);
88+
#[cfg_attr(
89+
feature = "serde",
90+
derive(serde::Serialize, serde::Deserialize),
91+
serde(transparent),
92+
serde(bound = "P: PointScaler")
93+
)]
94+
pub struct Point<P: PointScaler = Centi>(
95+
ClipperPoint64,
96+
#[cfg_attr(feature = "serde", serde(skip))] PhantomData<P>,
97+
);
8998

9099
impl<P: PointScaler> Point<P> {
91100
/// The zero point.
@@ -239,4 +248,15 @@ mod test {
239248
assert_eq!(point.x_scaled(), 2000);
240249
assert_eq!(point.y_scaled(), 4000);
241250
}
251+
252+
#[cfg(feature = "serde")]
253+
#[test]
254+
fn test_serde() {
255+
let point = Point::<Centi>::new(1.0, 2.0);
256+
let serialized = serde_json::to_string(&point).unwrap();
257+
assert_eq!(serialized, r#"{"x":100,"y":200}"#);
258+
259+
let deserialized: Point<Centi> = serde_json::from_str(&serialized).unwrap();
260+
assert_eq!(point, deserialized);
261+
}
242262
}

0 commit comments

Comments
 (0)