radicle-surf: serialize type for any kind of line

To help frontends with figuring out what kind of line is being talked
about for added and deleted files, the serialization of `Addition` and
`Deletion` always include a type. This mirrors the serialization of
the `Modification` type, which is tagged because it's an enum.

The serialization is hand-rolled since it is desirable to make sure
that added files and deleted files are only ever composed of lines
that are not modified.

Signed-off-by: Fintan Halpenny <fintan.halpenny@gmail.com>
X-Clacks-Overhead: GNU Terry Pratchett
This commit is contained in:
Fintan Halpenny
2022-12-18 15:04:15 +00:00
parent 21c0e68ab5
commit f4d2e38620
2 changed files with 104 additions and 12 deletions
+76 -10
View File
@@ -238,23 +238,15 @@ impl Serialize for Line {
/// Either the modification of a single [`Line`], or just contextual
/// information.
#[cfg_attr(
feature = "serde",
derive(Serialize),
serde(tag = "type", rename_all = "camelCase")
)]
#[derive(Clone, Debug, PartialEq, Eq)]
pub enum Modification {
/// A lines is an addition in a file.
#[cfg_attr(feature = "serde", serde(rename_all = "camelCase"))]
Addition(Addition),
/// A lines is a deletion in a file.
#[cfg_attr(feature = "serde", serde(rename_all = "camelCase"))]
Deletion(Deletion),
/// A contextual line in a file, i.e. there were no changes to the line.
#[cfg_attr(feature = "serde", serde(rename_all = "camelCase"))]
Context {
line: Line,
line_no_old: u32,
@@ -262,22 +254,96 @@ pub enum Modification {
},
}
#[cfg(feature = "serde")]
impl Serialize for Modification {
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where
S: Serializer,
{
use serde::ser::SerializeMap as _;
const NAME: &str = "Modification";
const ADDITION: &str = "Addition";
const DELETION: &str = "Deletion";
const CONTEXT: &str = "Context";
match self {
Modification::Addition(addition) => {
let mut map = serializer.serialize_map(Some(3))?;
map.serialize_entry("line", &addition.line)?;
map.serialize_entry("lineNo", &addition.line_no)?;
map.serialize_entry("type", "addition")?;
map.end()
},
Modification::Deletion(deletion) => {
let mut map = serializer.serialize_map(Some(3))?;
map.serialize_entry("line", &deletion.line)?;
map.serialize_entry("lineNo", &deletion.line_no)?;
map.serialize_entry("type", "deletion")?;
map.end()
},
Modification::Context {
line,
line_no_old,
line_no_new,
} => {
let mut map = serializer.serialize_map(Some(4))?;
map.serialize_entry("line", line)?;
map.serialize_entry("lineNoOld", line_no_old)?;
map.serialize_entry("lineNoNew", line_no_new)?;
map.serialize_entry("type", "context")?;
map.end()
},
}
}
}
/// A addition of a [`Line`] at the `line_no`.
#[cfg_attr(feature = "serde", derive(Serialize), serde(rename_all = "camelCase"))]
#[derive(Clone, Debug, PartialEq, Eq)]
pub struct Addition {
pub line: Line,
pub line_no: u32,
}
#[cfg(feature = "serde")]
impl Serialize for Addition {
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where
S: Serializer,
{
use serde::ser::SerializeStruct as _;
let mut s = serializer.serialize_struct("Addition", 3)?;
s.serialize_field("line", &self.line)?;
s.serialize_field("lineNo", &self.line_no)?;
s.serialize_field("type", "addition")?;
s.end()
}
}
/// A deletion of a [`Line`] at the `line_no`.
#[cfg_attr(feature = "serde", derive(Serialize), serde(rename_all = "camelCase"))]
#[derive(Clone, Debug, PartialEq, Eq)]
pub struct Deletion {
pub line: Line,
pub line_no: u32,
}
#[cfg(feature = "serde")]
impl Serialize for Deletion {
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where
S: Serializer,
{
use serde::ser::SerializeStruct as _;
let mut s = serializer.serialize_struct("Deletion", 3)?;
s.serialize_field("line", &self.line)?;
s.serialize_field("lineNo", &self.line_no)?;
s.serialize_field("type", "deletion")?;
s.end()
}
}
impl Modification {
pub fn addition(line: impl Into<Line>, line_no: u32) -> Self {
Self::Addition(Addition {
+28 -2
View File
@@ -5,6 +5,8 @@ use radicle_surf::{
diff::{
Added,
Addition,
Deleted,
Deletion,
Diff,
EofNewLine,
FileDiff,
@@ -160,7 +162,17 @@ fn test_diff_serde() {
}].into()
}
}],
deleted: vec![],
deleted: vec![ Deleted {
path: Path::new("DCO").to_path_buf(),
diff: FileDiff::Plain {
hunks: vec![Hunk {
header: Line::from(b"@@ -0,0 +1,1".to_vec()),
lines: vec![
Deletion { line: Line::from(b"TODO".to_vec()), line_no: 1 }
]
}].into()
}
}],
moved: vec![ Moved {
old_path: Path::new("CONTRIBUTING").to_path_buf(),
new_path: Path::new("CONTRIBUTING.md").to_path_buf(),
@@ -199,11 +211,25 @@ fn test_diff_serde() {
"lines": [{
"line": "MIT",
"lineNo": 1,
"type": "addition",
}]
}]
},
}],
"deleted": [{
"path": "DCO",
"diff": {
"type": "plain",
"hunks": [{
"header": "@@ -0,0 +1,1",
"lines": [{
"line": "TODO",
"lineNo": 1,
"type": "deletion",
}]
}]
},
}],
"deleted": [],
"moved": [{ "oldPath": "CONTRIBUTING", "newPath": "CONTRIBUTING.md" }],
"copied": [],
"modified": [{