Skip to content
Draft
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
10 changes: 10 additions & 0 deletions .gitattributes
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
# Auto detect text files and normalize line endings to LF
* text=auto eol=lf

# generated & committed
cdevents-sdk/src/generated/** linguist-generated=true gitlab-generated

# Lock files (generated but should be diffed)
Cargo.lock linguist-generated=false
package-lock.json linguist-generated=false
bun.lockb binary
4 changes: 4 additions & 0 deletions .gitmodules
Original file line number Diff line number Diff line change
Expand Up @@ -9,3 +9,7 @@
path = cdevents-specs/spec-v0.4
url = https://github.com/cdevents/spec.git
branch = spec-v0.4
[submodule "cdevents-specs/spec-v0.5"]
path = cdevents-specs/spec-v0.5
url = https://github.com/cdevents/spec.git
branch = spec-v0.5
1 change: 1 addition & 0 deletions .mise.toml
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,7 @@ run = [
# "git submodule add -f https://github.com/cdevents/spec.git cdevents-specs/main",
# "git submodule add -f -b spec-v0.3 https://github.com/cdevents/spec.git cdevents-specs/spec-v0.3",
# "git submodule add -f -b spec-v0.4 https://github.com/cdevents/spec.git cdevents-specs/spec-v0.4",
# "git submodule add -f -b spec-v0.5 https://github.com/cdevents/spec.git cdevents-specs/spec-v0.5",
# "git submodule update -f --rebase -- cdevents-specs/main",
# ]

Expand Down
4 changes: 0 additions & 4 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -5,10 +5,6 @@ members = ["cdevents-sdk", "generator"]
[workspace.package]
edition = "2024"
version = "0.2.1"
authors = [
# The actual list of contributors can be retrieved from the git log
"The CDEvents Rust SDK Authors",
]
license = "Apache-2.0"
repository = "https://github.com/cdevents/sdk-rust"
rust-version = "1.85"
Expand Down
13 changes: 7 additions & 6 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,16 +9,16 @@ The SDK can be used to create CDEvents and send them as CloudEvents, as well as
Import the modules in your code

```toml
cdevents-sdk = "0.1"
cdevents-sdk = "0.3"
```

To send a CDEvent as CloudEvent:

```rust
````rust
// from examples/pipelinerun_finished.rs
use std::error::Error;

use cdevents_sdk::{CDEvent, Subject, spec_0_3_0::pipelinerun_finished, Content};
use cdevents_sdk::{CDEvent, Subject, spec_0_5_0::pipelinerun_finished, Content};
use cloudevents::{Event, AttributesReader};

fn main() -> Result<(), Box<dyn Error>> {
Expand All @@ -27,7 +27,7 @@ fn main() -> Result<(), Box<dyn Error>> {
errors: Some("pipelineErrors".into()),
outcome: Some("success".into()),
pipeline_name: Some("testPipeline".into()),
url: Some("https://dev.pipeline.run/url".into())
uri: Some("https://dev.pipeline.run/url".into())
})
.with_id("/dev/pipeline/run/1".try_into()?)
.with_source("https://dev.pipeline.run/source".try_into()?)
Expand Down Expand Up @@ -56,14 +56,15 @@ fn main() -> Result<(), Box<dyn Error>> {
assert_eq!(cdevent_expected, cdevent_extracted);
Ok(())
}
```
````

See the [CloudEvents](https://github.com/cloudevents/sdk-rust) docs as well.

## Features

- [x] support cdevents spec 0.3.0
- [x] support cdevents spec 0.5.0
- [x] support cdevents spec 0.4.1
- [x] support cdevents spec 0.3.0
- [ ] support of custom event
- [ ] compile-time generation of type for custom event
- [ ] runtime validation (download of jsonschemas & validation)
Expand Down
2 changes: 1 addition & 1 deletion cdevents-sdk/Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
[package]
name = "cdevents-sdk"
version.workspace = true
authors.workspace = true
edition.workspace = true
license.workspace = true
publish = true
Expand All @@ -12,6 +11,7 @@ description = "A Rust SDK for CDEvents"

[dependencies]
cloudevents-sdk = { version = "0.9", optional = true, default-features = false }
enum_dispatch = "0.3"
fluent-uri = { version = "0.4", features = ["serde"] }
proptest = { version = "1", optional = true }
proptest-derive = { version = "0.7", optional = true }
Expand Down
5 changes: 2 additions & 3 deletions cdevents-sdk/examples/pipelinerun_finished.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,9 +7,9 @@ fn main() -> Result<(), Box<dyn Error>> {
let cdevent = CDEvent::from(
Subject::from(pipelinerun_finished::Content{
errors: Some("pipelineErrors".into()),
outcome: Some("success".into()),
outcome: Some(pipelinerun_finished::ContentOutcome::Success),
pipeline_name: Some("testPipeline".into()),
url: Some("https://dev.pipeline.run/url".into())
uri: Some("https://dev.pipeline.run/url".try_into()?)
})
.with_id("/dev/pipeline/run/1".try_into()?)
.with_source("https://dev.pipeline.run/source".try_into()?)
Expand Down Expand Up @@ -38,4 +38,3 @@ fn main() -> Result<(), Box<dyn Error>> {
assert_eq!(cdevent_expected, cdevent_extracted);
Ok(())
}

56 changes: 29 additions & 27 deletions cdevents-sdk/src/cdevent.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
use crate::{Context, Id, Subject, UriReference};
use crate::{Context, ContextEnum, Id, Subject, UriReference};
use serde::{
de::{self, Deserializer, MapAccess, Visitor},
Deserialize, Serialize,
Expand All @@ -8,7 +8,7 @@ use std::fmt;
#[derive(Debug, Clone, Serialize, PartialEq, Eq)]
#[serde(deny_unknown_fields)]
pub struct CDEvent {
context: Context,
context: ContextEnum,
subject: Subject,
#[serde(rename = "customData", skip_serializing_if = "Option::is_none")]
custom_data: Option<serde_json::Value>,
Expand All @@ -21,10 +21,8 @@ pub struct CDEvent {

impl From<Subject> for CDEvent {
fn from(subject: Subject) -> Self {
let context = Context {
ty: subject.content().ty().into(),
..Default::default()
};
// TODO select context from subject version
let context = crate::new_context(subject.content().ty());
Self {
context,
subject,
Expand All @@ -37,41 +35,41 @@ impl From<Subject> for CDEvent {
impl CDEvent {
/// see <https://github.com/cdevents/spec/blob/main/spec.md#version>
pub fn version(&self) -> &str {
self.context.version.as_str()
self.context.version()
}

pub fn with_version<T>(mut self, v: T) -> Self where T: Into<String> {
self.context.version = v.into();
self
}
// pub fn with_version<T>(mut self, v: T) -> Self where T: Into<String> {
// self.context.with_version(v);
// self
// }

/// see <https://github.com/cdevents/spec/blob/main/spec.md#id-context>
pub fn id(&self) -> &Id {
&self.context.id
self.context.id()
}

pub fn with_id(mut self, v: Id) -> Self {
self.context.id = v;
self.context = self.context.with_id(v);
self
}

/// see <https://github.com/cdevents/spec/blob/main/spec.md#source-context>
pub fn source(&self) -> &UriReference {
&self.context.source
self.context.source()
}

pub fn with_source(mut self, v: UriReference) -> Self {
self.context.source = v;
self.context = self.context.with_source(v);
self
}

/// see <https://github.com/cdevents/spec/blob/main/spec.md#timestamp>
pub fn timestamp(&self) -> &time::OffsetDateTime {
&self.context.timestamp
self.context.timestamp()
}

pub fn with_timestamp(mut self, v: time::OffsetDateTime) -> Self {
self.context.timestamp = v;
self.context = self.context.with_timestamp(v);
self
}

Expand All @@ -84,7 +82,7 @@ impl CDEvent {
/// derived from subject.content
pub fn ty(&self) -> &str {
//self.subject.content().ty()
self.context.ty.as_str()
self.context.ty()
}

/// see <https://github.com/cdevents/spec/blob/main/spec.md#customdata>
Expand Down Expand Up @@ -127,6 +125,7 @@ impl<'de> Deserialize<'de> for CDEvent {

struct CDEventVisitor;

// TODO remove dependencie to serde_json
impl<'de> Visitor<'de> for CDEventVisitor {
type Value = CDEvent;

Expand All @@ -138,17 +137,17 @@ impl<'de> Deserialize<'de> for CDEvent {
where
V: MapAccess<'de>,
{
let mut context: Option<Context> = None;
let mut context_json: Option<serde_json::value::Value> = None;
let mut subject_json: Option<serde_json::value::Value> = None;
let mut custom_data = None;
let mut custom_data_content_type = None;
while let Some(key) = map.next_key()? {
match key {
Field::Context => {
if context.is_some() {
if context_json.is_some() {
return Err(de::Error::duplicate_field("context"));
}
context = Some(map.next_value()?);
context_json = Some(map.next_value()?);
}
Field::Subject => {
if subject_json.is_some() {
Expand All @@ -170,11 +169,14 @@ impl<'de> Deserialize<'de> for CDEvent {
}
}
}
let context = context.ok_or_else(|| de::Error::missing_field("context"))?;
let subject_json =
subject_json.ok_or_else(|| de::Error::missing_field("subject"))?;
let subject =
Subject::from_json(&context.ty, subject_json).map_err(de::Error::custom)?;
let context = {
let context_json = context_json.ok_or_else(|| de::Error::missing_field("context"))?;
ContextEnum::from_json(context_json).map_err(de::Error::custom)?
};
let subject = {
let subject_json = subject_json.ok_or_else(|| de::Error::missing_field("subject"))?;
Subject::from_json(context.ty(), subject_json).map_err(de::Error::custom)?
};

Ok(CDEvent {
context,
Expand Down Expand Up @@ -221,4 +223,4 @@ mod tests {
assert_eq!(s, actual);
}
}
}
}
Loading
Loading