Skip to content

Commit

Permalink
Fix schema serialization (#771)
Browse files Browse the repository at this point in the history
Signed-off-by: Kesha Hietala <[email protected]>
  • Loading branch information
khieta authored Apr 3, 2024
1 parent 5364814 commit 3875431
Show file tree
Hide file tree
Showing 4 changed files with 312 additions and 190 deletions.
39 changes: 5 additions & 34 deletions .github/workflows/build_downstream_deps.yml
Original file line number Diff line number Diff line change
Expand Up @@ -17,41 +17,12 @@ jobs:
outputs:
branch_name: ${{ steps.get_branch_name.outputs.branch_name }}

cedar-drt:
name: CedarDRT
runs-on: ubuntu-latest
build-cedar-drt:
needs: get-branch-name
strategy:
matrix:
toolchain:
- stable
steps:
- run: rustup update ${{ matrix.toolchain }} && rustup default ${{ matrix.toolchain }}
- name: Install Lean
shell: bash
run: |
wget https://raw.githubusercontent.com/leanprover/elan/master/elan-init.sh
bash elan-init.sh -y
- name: Checkout cedar-spec
uses: actions/checkout@v4
with:
repository: cedar-policy/cedar-spec
ref: ${{ needs.get-branch-name.outputs.branch_name }}
path: ./cedar-spec
- name: checkout cedar
uses: actions/checkout@v4
with:
path: cedar-spec/cedar
- name: build cedar-lean
working-directory: cedar-spec/cedar-lean
shell: bash
run: source ~/.profile && lake build Cedar:static DiffTest:static Std:static
- name: build cedar-drt
working-directory: cedar-spec/cedar-drt
run: source ~/.profile && source ./set_env_vars.sh && RUSTFLAGS="-D warnings" cargo build
- name: build cedar-drt/fuzz
working-directory: cedar-spec/cedar-drt/fuzz
run: source ~/.profile && source ../set_env_vars.sh && RUSTFLAGS="--cfg=fuzzing -D warnings" cargo build
uses: cedar-policy/cedar-spec/.github/workflows/build_and_test_drt_reusable.yml@main
with:
cedar_policy_ref: ${{ github.ref }}
cedar_spec_ref: ${{ needs.get-branch-name.outputs.branch_name }}

build-cedar-java:
needs: get-branch-name
Expand Down
33 changes: 31 additions & 2 deletions cedar-policy-core/src/ast/id.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
use serde::{Deserialize, Serialize};
use serde::{Deserialize, Deserializer, Serialize};
use smol_str::SmolStr;

use crate::{parser::err::ParseErrors, FromNormalizedStr};
Expand All @@ -9,7 +9,7 @@ use crate::{parser::err::ParseErrors, FromNormalizedStr};
/// `true | false | if | then | else | in | is | like | has`).
//
// For now, internally, `Id`s are just owned `SmolString`s.
#[derive(Serialize, Deserialize, Debug, PartialEq, Eq, Clone, Hash, PartialOrd, Ord)]
#[derive(Serialize, Debug, PartialEq, Eq, Clone, Hash, PartialOrd, Ord)]
pub struct Id(SmolStr);

impl Id {
Expand Down Expand Up @@ -63,6 +63,35 @@ impl FromNormalizedStr for Id {
}
}

struct IdVisitor;

impl<'de> serde::de::Visitor<'de> for IdVisitor {
type Value = Id;

fn expecting(&self, formatter: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
formatter.write_str("a valid id")
}

fn visit_str<E>(self, value: &str) -> Result<Self::Value, E>
where
E: serde::de::Error,
{
Id::from_normalized_str(value)
.map_err(|err| serde::de::Error::custom(format!("invalid id `{value}`: {err}")))
}
}

/// Deserialize an `Id` using `from_normalized_str`.
/// This deserialization implementation is used in the JSON schema format.
impl<'de> Deserialize<'de> for Id {
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
where
D: Deserializer<'de>,
{
deserializer.deserialize_str(IdVisitor)
}
}

#[cfg(feature = "arbitrary")]
impl<'a> arbitrary::Arbitrary<'a> for Id {
fn arbitrary(u: &mut arbitrary::Unstructured<'a>) -> arbitrary::Result<Self> {
Expand Down
47 changes: 43 additions & 4 deletions cedar-policy-core/src/ast/name.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,8 @@

use super::id::Id;
use itertools::Itertools;
use serde::{Deserialize, Serialize};
use serde::{Deserialize, Deserializer, Serialize, Serializer};
use smol_str::ToSmolStr;
use std::sync::Arc;

use crate::parser::err::ParseErrors;
Expand All @@ -28,7 +29,7 @@ use super::PrincipalOrResource;
/// This is the `Name` type used to name types, functions, etc.
/// The name can include namespaces.
/// Clone is O(1).
#[derive(Serialize, Deserialize, Debug, PartialEq, Eq, Clone, Hash, PartialOrd, Ord)]
#[derive(Debug, PartialEq, Eq, Clone, Hash, PartialOrd, Ord)]
#[cfg_attr(feature = "arbitrary", derive(arbitrary::Arbitrary))]
pub struct Name {
/// Basename
Expand Down Expand Up @@ -152,6 +153,17 @@ impl std::fmt::Display for Name {
}
}

/// Serialize a `Name` using its `Display` implementation
/// This serialization implementation is used in the JSON schema format.
impl Serialize for Name {
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where
S: Serializer,
{
self.to_smolstr().serialize(serializer)
}
}

// allow `.parse()` on a string to make a `Name`
impl std::str::FromStr for Name {
type Err = ParseErrors;
Expand All @@ -167,6 +179,35 @@ impl FromNormalizedStr for Name {
}
}

struct NameVisitor;

impl<'de> serde::de::Visitor<'de> for NameVisitor {
type Value = Name;

fn expecting(&self, formatter: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
formatter.write_str("a name consisting of an optional namespace and id")
}

fn visit_str<E>(self, value: &str) -> Result<Self::Value, E>
where
E: serde::de::Error,
{
Name::from_normalized_str(value)
.map_err(|err| serde::de::Error::custom(format!("invalid name `{value}`: {err}")))
}
}

/// Deserialize a `Name` using `from_normalized_str`
/// This deserialization implementation is used in the JSON schema format.
impl<'de> Deserialize<'de> for Name {
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
where
D: Deserializer<'de>,
{
deserializer.deserialize_str(NameVisitor)
}
}

/// Identifier for a slot
/// Clone is O(1).
// This simply wraps a separate enum -- currently `ValidSlotId` -- in case we
Expand Down Expand Up @@ -275,8 +316,6 @@ mod vars_test {

#[cfg(test)]
mod test {
use smol_str::ToSmolStr;

use super::*;

#[test]
Expand Down
Loading

0 comments on commit 3875431

Please sign in to comment.