Skip to content

Commit

Permalink
feat(crypto-helper): asn1: implement hex view PoC
Browse files Browse the repository at this point in the history
  • Loading branch information
TheBestTvarynka committed Dec 3, 2023
1 parent 4cb4813 commit 944fb9b
Show file tree
Hide file tree
Showing 11 changed files with 136 additions and 51 deletions.
7 changes: 2 additions & 5 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

5 changes: 4 additions & 1 deletion crates/prop-strategies/src/constructors.rs
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,8 @@ pub fn recursive_empty_asn1_type() -> impl Strategy<Value = OwnedAsn1Type> {
let application_tag_inner = inner.clone();
prop_oneof![
vec(inner, 1..16).prop_map(|fields| {
Asn1Type::Sequence(OwnedSequence::from(
Asn1Type::Sequence(OwnedSequence::new(
0,
fields
.into_iter()
.map(|asn1_type| OwnedAsn1::new(Default::default(), Box::new(asn1_type)))
Expand All @@ -33,12 +34,14 @@ pub fn recursive_empty_asn1_type() -> impl Strategy<Value = OwnedAsn1Type> {
(0_u8..31)
.prop_flat_map(move |tag| (Just(tag), explicit_tag_inner.clone()))
.prop_map(|(tag, inner)| Asn1Type::ExplicitTag(OwnedExplicitTag::new(
0,
tag,
OwnedAsn1::new(Default::default(), Box::new(inner))
))),
(0_u8..31)
.prop_flat_map(move |tag| (Just(tag), application_tag_inner.clone()))
.prop_map(|(tag, inner)| Asn1Type::ApplicationTag(OwnedApplicationTag::new(
0,
tag,
OwnedAsn1::new(Default::default(), Box::new(inner))
))),
Expand Down
4 changes: 2 additions & 2 deletions crates/prop-strategies/src/generic_types.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,9 @@ use proptest::prelude::any;
use proptest::strategy::{Just, Strategy};

pub fn any_bool() -> impl Strategy<Value = Bool> {
any::<bool>().prop_map(Bool::from)
any::<bool>().prop_map(|flag| Bool::new(0, flag))
}

pub fn any_null() -> impl Strategy<Value = Null> {
Just(Null)
Just(Null::default())
}
7 changes: 4 additions & 3 deletions crates/prop-strategies/src/string.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,14 +8,14 @@ const STRING_LEN: usize = 12;
prop_compose! {
pub fn any_octet_string()
(data in bytes(STRING_LEN)) -> OwnedOctetString {
OwnedOctetString::from(data)
OwnedOctetString::new_owned(0, data)
}
}

prop_compose! {
pub fn any_utf8_string()
(data in string(STRING_LEN)) -> OwnedUtf8String {
OwnedUtf8String::from(data)
OwnedUtf8String::new_owned(0, data)
}
}

Expand All @@ -26,6 +26,7 @@ prop_compose! {
unused_bits in 0..8_usize,
) -> OwnedBitString {
BitString::from_raw_vec(
0,
if data.is_empty() { 0 } else { data.len() * 8 - unused_bits },
data,
).unwrap()
Expand All @@ -35,6 +36,6 @@ prop_compose! {
prop_compose! {
pub fn any_bmp_string()
(data in string(STRING_LEN)) -> OwnedBmpString {
data.as_str().into()
OwnedBmpString::new_owned(0, data.into())
}
}
4 changes: 4 additions & 0 deletions public/styles/asn1/node.scss
Original file line number Diff line number Diff line change
Expand Up @@ -58,3 +58,7 @@
background-color: #ba0021;
color: #f5bdb6;
}

.hover_node {
border: 2px solid rebeccapurple;
}
24 changes: 21 additions & 3 deletions src/asn1.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
mod asn1_viewer;
mod hex_buffer;
mod scheme;
mod hex_view;
mod scheme;

use asn1_parser::Asn1;
use web_sys::KeyboardEvent;
Expand Down Expand Up @@ -41,6 +41,11 @@ pub const TEST_ASN1: &[u8] = &[
156, 243, 148, 132, 139, 241, 150, 160, 154, 241, 169, 185, 175, 226, 128, 174, 226, 128, 174, 0, 70, 45,
];

#[derive(Clone, Debug, PartialEq, Default)]
struct Asn1Context {
hover_node_id: Option<u64>,
}

#[function_component(Asn1ParserPage)]
pub fn asn1_parser_page() -> Html {
let auto_decode = use_state(|| true);
Expand Down Expand Up @@ -68,6 +73,10 @@ pub fn asn1_parser_page() -> Html {

let raw_asn1_setter = raw_asn1.setter();

let ctx = use_state(|| Option::<u64>::None);
let ctx_setter_asn1 = ctx.setter();
let ctx_setter_hex = ctx.setter();

html! {
<div class={classes!("vertical", "asn1-page")} {onkeydown}>
<ByteInput bytes={(*raw_asn1).clone()} setter={Callback::from(move |data| raw_asn1_setter.set(data))} placeholder={"asn1 data".to_owned()} rows={10} />
Expand All @@ -76,8 +85,17 @@ pub fn asn1_parser_page() -> Html {
<Checkbox id={"auto-decode-asn1".to_owned()} name={"auto-decode".to_owned()} checked={*auto_decode} {set_checked} />
</div>
<div class="asn1-viewers">
<Asn1Viewer data={(*raw_asn1).clone()} structure={(*parsed_asn1).clone()} />
<HexViewer />
<Asn1Viewer
structure={(*parsed_asn1).clone()}
cur_node={(*ctx).clone()}
set_cur_node={move |id| ctx_setter_asn1.set(id)}
/>
<HexViewer
raw_data={(*raw_asn1).clone()}
structure={(*parsed_asn1).clone()}
cur_node={(*ctx).clone()}
set_cur_node={move |id| ctx_setter_hex.set(id)}
/>
</div>
</div>
}
Expand Down
8 changes: 5 additions & 3 deletions src/asn1/asn1_viewer.rs
Original file line number Diff line number Diff line change
@@ -1,19 +1,21 @@
use asn1_parser::OwnedAsn1;
use yew::{function_component, html, Html, Properties};
use yew::{function_component, html, Callback, Html, Properties};

use crate::asn1::scheme::build_asn1_schema;

#[derive(PartialEq, Properties, Clone)]
pub struct Asn1ViewerProps {
pub data: Vec<u8>,
pub structure: OwnedAsn1,

pub cur_node: Option<u64>,
pub set_cur_node: Callback<Option<u64>>,
}

#[function_component(Asn1Viewer)]
pub fn asn1_viewer(props: &Asn1ViewerProps) -> Html {
html! {
<div>
{build_asn1_schema(&props.structure)}
{build_asn1_schema(&props.structure, &props.cur_node)}
</div>
}
}
31 changes: 28 additions & 3 deletions src/asn1/hex_view.rs
Original file line number Diff line number Diff line change
@@ -1,10 +1,35 @@
use yew::{function_component, html, Html, Properties};
use asn1_parser::OwnedAsn1;
use web_sys::MouseEvent;
use yew::{function_component, html, use_context, Callback, Html, Properties};

#[derive(PartialEq, Properties, Clone)]
pub struct HexViewerProps {
pub raw_data: Vec<u8>,
pub structure: OwnedAsn1,

pub cur_node: Option<u64>,
pub set_cur_node: Callback<Option<u64>>,
}

#[function_component(HexViewer)]
pub fn hex_viewer() -> Html {
pub fn hex_viewer(props: &HexViewerProps) -> Html {
let cur_node = props.cur_node.clone();

let set_cur_node = props.set_cur_node.clone();
let onmouseenter = Callback::from(move |_: MouseEvent| {
log::debug!("Mouse enter event! {:?}", cur_node);
set_cur_node.emit(Some(3));
});

let set_cur_node = props.set_cur_node.clone();
let onmouseleave = Callback::from(move |_: MouseEvent| {
log::debug!("Mouse leave event! {:?}", cur_node);
set_cur_node.emit(None);
});

html! {
<div class="asn1-hex-viewer">
<span>{"HexView"}</span>
<span {onmouseenter} {onmouseleave}>{"third elem show yourself"}</span>
</div>
}
}
83 changes: 56 additions & 27 deletions src/asn1/scheme.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,58 +3,87 @@ mod sequence;
mod strings;
mod tag;

use asn1_parser::{Asn1, Asn1Type};
use yew::html;
use asn1_parser::{Asn1, Asn1Entity, Asn1Type};
use yew::virtual_dom::VNode;
use yew::{classes, function_component, html, Children, Classes, Html, Properties};

use self::primitive::{BoolNode, NullNode};
use self::sequence::SequenceNode;
use self::strings::{BitStringNode, BmpStringNode, OctetStringNode, Utf8StringNode};
use self::tag::{ApplicationTagNode, ExplicitTagNode};

// #[derive(PartialEq, Properties, Clone)]
// pub struct Asn1SchemeProps {
// pub schema: OwnedAsn1,
// }
#[derive(PartialEq, Properties, Clone)]
pub struct Asn1NodeProps {
pub id: u64,
pub cur_id: Option<u64>,

pub fn build_asn1_schema(asn1: &Asn1<'_>) -> VNode {
pub children: Children,
}

#[function_component(Asn1Node)]
pub fn asn1_node(props: &Asn1NodeProps) -> Html {
fn compare_ids(id: u64, cur_id: &Option<u64>) -> Classes {
log::debug!("compare: {} {:?}", id, cur_id);
match cur_id {
Some(cur_id) if *cur_id == id => {
log::debug!("set class");
classes!("hover_node")
}
_ => classes!(""),
}
}

html! {
<div class={compare_ids(props.id, &props.cur_id)}>
{props.children.clone()}
</div>
}
}

pub fn build_asn1_schema(asn1: &Asn1<'_>, cur_node: &Option<u64>) -> VNode {
match asn1.asn1() {
Asn1Type::OctetString(octet) => html! {
<OctetStringNode node={octet.to_owned()} />
<Asn1Node id={octet.id()} cur_id={cur_node.clone()}>
<OctetStringNode node={octet.to_owned()} />
</Asn1Node>
},
Asn1Type::Utf8String(utf8) => html! {
<Utf8StringNode node={utf8.to_owned()} />
<Asn1Node id={utf8.id()} cur_id={cur_node.clone()}>
<Utf8StringNode node={utf8.to_owned()} />
</Asn1Node>
},
Asn1Type::Sequence(sequence) => html! {
<SequenceNode node={sequence.to_owned()} />
<SequenceNode node={sequence.to_owned()} cur_node={cur_node.clone()} />
},
Asn1Type::BitString(bit) => html! {
<BitStringNode node={bit.to_owned()} />
<Asn1Node id={bit.id()} cur_id={cur_node.clone()}>
<BitStringNode node={bit.to_owned()} />
</Asn1Node>
},
Asn1Type::Bool(boolean) => html! {
<BoolNode node={boolean.to_owned()} />
<Asn1Node id={boolean.id()} cur_id={cur_node.clone()}>
<BoolNode node={boolean.to_owned()} />
</Asn1Node>
},
Asn1Type::BmpString(bmp) => html! {
<BmpStringNode node={bmp.to_owned()} />
<Asn1Node id={bmp.id()} cur_id={cur_node.clone()}>
<BmpStringNode node={bmp.to_owned()} />
</Asn1Node>
},
Asn1Type::Null(_) => html! {
<NullNode />
Asn1Type::Null(null) => html! {
<Asn1Node id={null.id()} cur_id={cur_node.clone()}>
<NullNode />
</Asn1Node>
},
Asn1Type::ExplicitTag(explicit) => html! {
<ExplicitTagNode node={explicit.to_owned()} />
<Asn1Node id={explicit.id()} cur_id={cur_node.clone()}>
<ExplicitTagNode node={explicit.to_owned()} cur_node={cur_node.clone()} />
</Asn1Node>
},
Asn1Type::ApplicationTag(application) => html! {
<ApplicationTagNode node={application.to_owned()} />
<Asn1Node id={application.id()} cur_id={cur_node.clone()}>
<ApplicationTagNode node={application.to_owned()} cur_node={cur_node.clone()} />
</Asn1Node>
},
}
}

// #[function_component(Asn1Scheme)]
// pub fn asn1_scheme(props: &Asn1SchemeProps) -> Html {
// let node = ;

// html! {
// <div>
// </div>
// }
// }
8 changes: 6 additions & 2 deletions src/asn1/scheme/sequence.rs
Original file line number Diff line number Diff line change
@@ -1,18 +1,22 @@
use asn1_parser::OwnedSequence;
use asn1_parser::{Asn1Entity, OwnedSequence};
use yew::{function_component, html, Html, Properties};

use crate::asn1::scheme::build_asn1_schema;

#[derive(PartialEq, Properties, Clone)]
pub struct SequenceNodeProps {
pub node: OwnedSequence,
pub cur_node: Option<u64>,
}

#[function_component(SequenceNode)]
pub fn sequence(props: &SequenceNodeProps) -> Html {
let fields = props.node.fields();

let fields_components = fields.iter().map(|f| build_asn1_schema(f)).collect::<Vec<_>>();
let fields_components = fields
.iter()
.map(|f| build_asn1_schema(f, &props.cur_node))
.collect::<Vec<_>>();

html! {
<div>
Expand Down
6 changes: 4 additions & 2 deletions src/asn1/scheme/tag.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ use crate::asn1::scheme::build_asn1_schema;
#[derive(PartialEq, Properties, Clone)]
pub struct ExplicitTagProps {
pub node: OwnedExplicitTag,
pub cur_node: Option<u64>,
}

#[function_component(ExplicitTagNode)]
Expand All @@ -16,14 +17,15 @@ pub fn explicit_tag(props: &ExplicitTagProps) -> Html {
<span>{format!("[{}]", props.node.tag_number())}</span>
</div>
<div class="asn1-constructor-body">
{build_asn1_schema(props.node.inner())}
{build_asn1_schema(props.node.inner(), &props.cur_node)}
</div>
</div>
}
}
#[derive(PartialEq, Properties, Clone)]
pub struct ApplicationTagProps {
pub node: OwnedApplicationTag,
pub cur_node: Option<u64>,
}

#[function_component(ApplicationTagNode)]
Expand All @@ -34,7 +36,7 @@ pub fn application_tag(props: &ApplicationTagProps) -> Html {
<span>{format!("Application {}", props.node.tag_number())}</span>
</div>
<div class="asn1-constructor-body">
{build_asn1_schema(props.node.inner())}
{build_asn1_schema(props.node.inner(), &props.cur_node)}
</div>
</div>
}
Expand Down

0 comments on commit 944fb9b

Please sign in to comment.