Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(parse): add proto::PlanVersion parser #165

Merged
merged 1 commit into from
Mar 19, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 0 additions & 1 deletion .github/workflows/release.yml
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,6 @@ jobs:
${{ runner.os }}-cargo-
- run: cargo-smart-release --debug --locked || true
- run: cargo check --all-features
- run: cargo changelog --execute substrait
- run: |
git config user.name github-actions[bot]
git config user.email 41898282+github-actions[bot]@users.noreply.github.com
Expand Down
14 changes: 13 additions & 1 deletion src/parse/context.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,23 @@

//! A parse context.

use crate::parse::Parse;

/// A parse context.
///
/// Parsing Substrait data is context-sensitive. This trait provides methods
/// that can be used by parser implementations to parse Substrait data.
pub trait Context {}
pub trait Context {
/// Parse an item with this context.
///
/// See [Parse::parse].
fn parse<T: Parse<Self>>(&mut self, item: T) -> Result<T::Parsed, T::Error>
where
Self: Sized,
{
item.parse(self)
}
}

#[cfg(test)]
pub(crate) mod tests {
Expand Down
3 changes: 3 additions & 0 deletions src/parse/proto/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,3 +4,6 @@

mod version;
pub use version::{Version, VersionError};

mod plan_version;
pub use plan_version::{PlanVersion, PlanVersionError};
105 changes: 105 additions & 0 deletions src/parse/proto/plan_version.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,105 @@
// SPDX-License-Identifier: Apache-2.0

//! Parsing of [proto::PlanVersion].

use crate::{
parse::{context::Context, proto::Version, Parse},
proto,
};
use thiserror::Error;

use super::VersionError;

/// A parsed [proto::PlanVersion].
#[derive(Clone, Debug, PartialEq)]
pub struct PlanVersion {
/// The version of the plan.
version: Version,
}

impl PlanVersion {
/// Returns the version of this plan version.
///
/// See [proto::PlanVersion::version].
pub fn version(&self) -> &Version {
&self.version
}
}

/// Parse errors for [proto::PlanVersion].
#[derive(Debug, Error, PartialEq)]
pub enum PlanVersionError {
/// Version is missing.
#[error("version must be specified")]
Missing,

/// Version error.
#[error("version must be valid")]
Version(#[from] VersionError),
}

impl<C: Context> Parse<C> for proto::PlanVersion {
type Parsed = PlanVersion;
type Error = PlanVersionError;

fn parse(self, ctx: &mut C) -> Result<Self::Parsed, Self::Error> {
let proto::PlanVersion { version } = self;

// The version is required, and must be valid.
let version = version
.map(|version| ctx.parse(version))
.transpose()?
.ok_or(PlanVersionError::Missing)?;

let plan_version = PlanVersion { version };

Ok(plan_version)
}
}

impl From<PlanVersion> for proto::PlanVersion {
fn from(plan_version: PlanVersion) -> Self {
let PlanVersion { version } = plan_version;

proto::PlanVersion {
version: Some(version.into()),
}
}
}

#[cfg(test)]
mod tests {
use super::*;
use crate::{
parse::{context::tests::Context, proto::VersionError},
version,
};

#[test]
fn parse() {
let plan_version = proto::PlanVersion {
version: Some(version::version()),
};
assert!(plan_version.parse(&mut Context::default()).is_ok());
}

#[test]
fn missing() {
let plan_version = proto::PlanVersion::default();
assert_eq!(
plan_version.parse(&mut Context::default()),
Err(PlanVersionError::Missing)
);
}

#[test]
fn version_error() {
let plan_version = proto::PlanVersion {
version: Some(proto::Version::default()),
};
assert_eq!(
plan_version.parse(&mut Context::default()),
Err(PlanVersionError::Version(VersionError::Missing))
);
}
}
13 changes: 11 additions & 2 deletions src/parse/proto/version.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,10 @@

//! Parsing of [proto::Version].

use crate::parse::{context::Context, Parse};
use crate::{proto, version};
use crate::{
parse::{context::Context, Parse},
proto, version,
};
use hex::FromHex;
use thiserror::Error;

Expand All @@ -22,16 +24,23 @@ pub struct Version {

impl Version {
/// Returns the semantic version of this version.
///
/// See [proto::Version::major_number], [proto::Version::minor_number] and
/// [proto::Version::patch_number].
pub fn version(&self) -> &semver::Version {
&self.version
}

/// Returns the git hash of this version.
///
/// See [proto::Version::git_hash].
pub fn git_hash(&self) -> Option<&[u8; 20]> {
self.git_hash.as_ref()
}

/// Returns the producer of this version.
///
/// See [proto::Version::producer].
pub fn producer(&self) -> Option<&str> {
self.producer.as_deref()
}
Expand Down
2 changes: 1 addition & 1 deletion src/proto.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
clippy::needless_borrows_for_generic_args
)]

//! Generated types for the protobuf `substrait` package
//! Generated types for the protobuf `substrait` package.

/// Generated types for the protobuf `substrait.extensions` package
pub mod extensions {
Expand Down
2 changes: 1 addition & 1 deletion src/text.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
unused_variables
)]

//! Generated types for text-based definitions
//! Generated types for text-based definitions.

// https://github.com/oxidecomputer/typify/issues/245
include!(concat!(env!("OUT_DIR"), "/substrait_text.rs"));
Expand Down