Skip to content

Commit

Permalink
Merge pull request #1330 from hannobraun/validate
Browse files Browse the repository at this point in the history
Complete transition to new validation infrastructure
  • Loading branch information
hannobraun authored Nov 9, 2022
2 parents 6113fe6 + c874a9c commit 4ad557d
Show file tree
Hide file tree
Showing 12 changed files with 31 additions and 232 deletions.
2 changes: 1 addition & 1 deletion crates/fj-kernel/src/objects/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -104,7 +104,7 @@ use crate::{
storage::{Handle, Store},
validate::{
CycleValidationError, FaceValidationError, HalfEdgeValidationError,
SurfaceVertexValidationError, Validate2, VertexValidationError,
SurfaceVertexValidationError, Validate, VertexValidationError,
},
};

Expand Down
6 changes: 3 additions & 3 deletions crates/fj-kernel/src/validate/curve.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,9 @@ use std::convert::Infallible;

use crate::objects::{Curve, GlobalCurve};

use super::{Validate2, ValidationConfig};
use super::{Validate, ValidationConfig};

impl Validate2 for Curve {
impl Validate for Curve {
type Error = Infallible;

fn validate_with_config(
Expand All @@ -15,7 +15,7 @@ impl Validate2 for Curve {
}
}

impl Validate2 for GlobalCurve {
impl Validate for GlobalCurve {
type Error = Infallible;

fn validate_with_config(
Expand Down
6 changes: 3 additions & 3 deletions crates/fj-kernel/src/validate/cycle.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,9 @@ use crate::{
storage::Handle,
};

use super::{Validate2, ValidationConfig};
use super::{Validate, ValidationConfig};

impl Validate2 for Cycle {
impl Validate for Cycle {
type Error = CycleValidationError;

fn validate_with_config(
Expand Down Expand Up @@ -69,7 +69,7 @@ mod tests {
builder::{CycleBuilder, HalfEdgeBuilder, VertexBuilder},
objects::{Cycle, Objects},
partial::HasPartial,
validate::Validate2,
validate::Validate,
};

#[test]
Expand Down
8 changes: 4 additions & 4 deletions crates/fj-kernel/src/validate/edge.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,9 +11,9 @@ use crate::{
storage::Handle,
};

use super::{Validate2, ValidationConfig};
use super::{Validate, ValidationConfig};

impl Validate2 for HalfEdge {
impl Validate for HalfEdge {
type Error = HalfEdgeValidationError;

fn validate_with_config(
Expand All @@ -33,7 +33,7 @@ impl Validate2 for HalfEdge {
}
}

impl Validate2 for GlobalEdge {
impl Validate for GlobalEdge {
type Error = Infallible;

fn validate_with_config(
Expand Down Expand Up @@ -204,7 +204,7 @@ mod tests {
builder::{HalfEdgeBuilder, VertexBuilder},
objects::{GlobalCurve, HalfEdge, Objects},
partial::HasPartial,
validate::Validate2,
validate::Validate,
};

#[test]
Expand Down
6 changes: 3 additions & 3 deletions crates/fj-kernel/src/validate/face.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,9 @@ use crate::{
storage::Handle,
};

use super::{Validate2, ValidationConfig};
use super::{Validate, ValidationConfig};

impl Validate2 for Face {
impl Validate for Face {
type Error = FaceValidationError;

fn validate_with_config(
Expand Down Expand Up @@ -108,7 +108,7 @@ mod tests {
builder::CycleBuilder,
objects::{Cycle, Face, Objects},
partial::HasPartial,
validate::Validate2,
validate::Validate,
};

#[test]
Expand Down
158 changes: 4 additions & 154 deletions crates/fj-kernel/src/validate/mod.rs
Original file line number Diff line number Diff line change
@@ -1,18 +1,4 @@
//! Infrastructure for validating shapes
//!
//! Validation enforces various constraints about shapes and the objects that
//! constitute them. These constraints fall into 4 categories:
//!
//! - **Coherence:** Local forms of objects must be consistent with their
//! canonical forms.
//! - **Geometric:** Comprises various object-specific constraints, for example
//! edges or faces might not be allowed to intersect.
//! - **Structural:** All other objects that an object references must be part
//! of the same shape.
//! - **Uniqueness:** Objects within a shape must be unique.
//!
//! Please note that not all of these validation categories are fully
//! implemented, as of this writing.
//! Infrastructure for validating objects
mod curve;
mod cycle;
Expand All @@ -22,87 +8,23 @@ mod shell;
mod sketch;
mod solid;
mod surface;
mod uniqueness;
mod vertex;

pub use self::{
cycle::CycleValidationError,
edge::HalfEdgeValidationError,
face::FaceValidationError,
uniqueness::UniquenessIssues,
vertex::{SurfaceVertexValidationError, VertexValidationError},
};

use std::{collections::HashSet, convert::Infallible, ops::Deref};
use std::convert::Infallible;

use fj_math::Scalar;

use crate::iter::ObjectIters;

/// Validate an object
///
/// This trait is used automatically when inserting an object into a store.
pub trait Validate: Sized {
/// Validate the object using default configuration
///
/// The following calls are equivalent:
/// ``` rust
/// # use fj_kernel::{
/// # objects::{GlobalVertex, Objects},
/// # validate::{Validate, ValidationConfig},
/// # };
/// # let objects = Objects::new();
/// # let object = objects.global_vertices.insert(
/// # GlobalVertex::from_position([0., 0., 0.])
/// # );
/// object.validate();
/// ```
/// ``` rust
/// # use fj_kernel::{
/// # objects::{GlobalVertex, Objects},
/// # validate::{Validate, ValidationConfig},
/// # };
/// # let objects = Objects::new();
/// # let object = objects.global_vertices.insert(
/// # GlobalVertex::from_position([0., 0., 0.])
/// # );
/// object.validate_with_config(&ValidationConfig::default());
/// ```
fn validate(self) -> Result<Validated<Self>, ValidationError> {
self.validate_with_config(&ValidationConfig::default())
}

/// Validate the object
fn validate_with_config(
self,
config: &ValidationConfig,
) -> Result<Validated<Self>, ValidationError>;
}

impl<T> Validate for T
where
T: for<'r> ObjectIters<'r>,
{
fn validate_with_config(
self,
config: &ValidationConfig,
) -> Result<Validated<Self>, ValidationError> {
let mut global_vertices = HashSet::new();

for global_vertex in self.global_vertex_iter() {
uniqueness::validate_vertex(
global_vertex,
&global_vertices,
config.distinct_min_distance,
)?;

global_vertices.insert(*global_vertex);
}

Ok(Validated(self))
}
}

/// Validate an object
pub trait Validate2: Sized {
/// The error that validation of the implementing type can result in
type Error: Into<ValidationError>;

Expand Down Expand Up @@ -150,35 +72,10 @@ impl Default for ValidationConfig {
}
}

/// Wrapper around an object that indicates the object has been validated
///
/// Returned by implementations of `Validate`.
#[derive(Clone, Copy, Debug, Eq, PartialEq, Hash, Ord, PartialOrd)]
pub struct Validated<T>(T);

impl<T> Validated<T> {
/// Consume this instance of `Validated` and return the wrapped object
pub fn into_inner(self) -> T {
self.0
}
}

impl<T> Deref for Validated<T> {
type Target = T;

fn deref(&self) -> &Self::Target {
&self.0
}
}

/// An error that can occur during a validation
#[allow(clippy::large_enum_variant)]
#[derive(Debug, thiserror::Error)]
pub enum ValidationError {
/// Uniqueness validation failed
#[error("Uniqueness validation failed")]
Uniqueness(#[from] UniquenessIssues),

/// `Cycle` validation error
#[error(transparent)]
Cycle(#[from] CycleValidationError),
Expand All @@ -205,50 +102,3 @@ impl From<Infallible> for ValidationError {
match infallible {}
}
}

#[cfg(test)]
mod tests {
use fj_math::{Point, Scalar};

use crate::{
objects::{GlobalVertex, Objects},
validate::{Validate, ValidationConfig, ValidationError},
};

#[test]
fn uniqueness_vertex() -> anyhow::Result<()> {
let objects = Objects::new();
let mut shape = Vec::new();

let deviation = Scalar::from_f64(0.25);

let a = Point::from([0., 0., 0.]);

let mut b = a;
b.x += deviation;

let config = ValidationConfig {
distinct_min_distance: deviation * 2.,
..ValidationConfig::default()
};

// Adding a vertex should work.
shape.push(
objects
.global_vertices
.insert(GlobalVertex::from_position(a)),
);
shape.clone().validate_with_config(&config)?;

// Adding a second vertex that is considered identical should fail.
shape.push(
objects
.global_vertices
.insert(GlobalVertex::from_position(b)),
);
let result = shape.validate_with_config(&config);
assert!(matches!(result, Err(ValidationError::Uniqueness(_))));

Ok(())
}
}
4 changes: 2 additions & 2 deletions crates/fj-kernel/src/validate/shell.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,9 @@ use std::convert::Infallible;

use crate::objects::Shell;

use super::{Validate2, ValidationConfig};
use super::{Validate, ValidationConfig};

impl Validate2 for Shell {
impl Validate for Shell {
type Error = Infallible;

fn validate_with_config(
Expand Down
4 changes: 2 additions & 2 deletions crates/fj-kernel/src/validate/sketch.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,9 @@ use std::convert::Infallible;

use crate::objects::Sketch;

use super::{Validate2, ValidationConfig};
use super::{Validate, ValidationConfig};

impl Validate2 for Sketch {
impl Validate for Sketch {
type Error = Infallible;

fn validate_with_config(
Expand Down
4 changes: 2 additions & 2 deletions crates/fj-kernel/src/validate/solid.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,9 @@ use std::convert::Infallible;

use crate::objects::Solid;

use super::{Validate2, ValidationConfig};
use super::{Validate, ValidationConfig};

impl Validate2 for Solid {
impl Validate for Solid {
type Error = Infallible;

fn validate_with_config(
Expand Down
4 changes: 2 additions & 2 deletions crates/fj-kernel/src/validate/surface.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,9 @@ use std::convert::Infallible;

use crate::objects::Surface;

use super::{Validate2, ValidationConfig};
use super::{Validate, ValidationConfig};

impl Validate2 for Surface {
impl Validate for Surface {
type Error = Infallible;

fn validate_with_config(
Expand Down
51 changes: 0 additions & 51 deletions crates/fj-kernel/src/validate/uniqueness.rs

This file was deleted.

Loading

0 comments on commit 4ad557d

Please sign in to comment.