mirror of
https://github.com/fluencelabs/aquavm
synced 2025-03-15 04:30:48 +00:00
fix(aquavm): temporary fix entire value in canon (#358)
This commit is contained in:
parent
076045124c
commit
eafdec5d86
18
.github/workflows/e2e.yml
vendored
18
.github/workflows/e2e.yml
vendored
@ -40,7 +40,7 @@ jobs:
|
||||
|
||||
uses: fluencelabs/fluence-js/.github/workflows/tests.yml@master
|
||||
with:
|
||||
avm-version: ${{ needs.snapshot.outputs.avm-version }}
|
||||
avm-version: "${{ needs.snapshot.outputs.avm-version }}"
|
||||
|
||||
fluence-js-snapshot:
|
||||
name: "fluence-js"
|
||||
@ -49,7 +49,7 @@ jobs:
|
||||
|
||||
uses: fluencelabs/fluence-js/.github/workflows/snapshot.yml@master
|
||||
with:
|
||||
avm-version: ${{ needs.snapshot.outputs.avm-version }}
|
||||
avm-version: "${{ needs.snapshot.outputs.avm-version }}"
|
||||
|
||||
aqua-snapshot:
|
||||
name: "aqua"
|
||||
@ -58,7 +58,7 @@ jobs:
|
||||
|
||||
uses: fluencelabs/aqua/.github/workflows/snapshot.yml@main
|
||||
with:
|
||||
fluence-js-version: ${{ needs.fluence-js-snapshot.outputs.fluence-js-version }}
|
||||
fluence-js-version: "${{ needs.fluence-js-snapshot.outputs.fluence-js-version }}"
|
||||
|
||||
aqua-playground:
|
||||
needs:
|
||||
@ -68,9 +68,9 @@ jobs:
|
||||
|
||||
uses: fluencelabs/aqua-playground/.github/workflows/tests.yml@master
|
||||
with:
|
||||
fluence-js-version: ${{ needs.fluence-js-snapshot.outputs.fluence-js-version }}
|
||||
aqua-version: ${{ needs.aqua-snapshot.outputs.aqua-version }}
|
||||
rust-peer-image: ${{ needs.rust-peer.outputs.rust-peer-image }}
|
||||
fluence-js-version: "${{ needs.fluence-js-snapshot.outputs.fluence-js-version }}"
|
||||
aqua-version: "${{ needs.aqua-snapshot.outputs.aqua-version }}"
|
||||
rust-peer-image: "${{ needs.rust-peer.outputs.rust-peer-image }}"
|
||||
|
||||
registry:
|
||||
needs:
|
||||
@ -79,7 +79,7 @@ jobs:
|
||||
|
||||
uses: fluencelabs/registry/.github/workflows/tests.yml@main
|
||||
with:
|
||||
aqua-version: ${{ needs.aqua-snapshot.outputs.aqua-version }}
|
||||
rust-peer-image: ${{ needs.rust-peer.outputs.rust-peer-image }}
|
||||
aqua-version: "${{ needs.aqua-snapshot.outputs.aqua-version }}"
|
||||
rust-peer-image: "${{ needs.rust-peer.outputs.rust-peer-image }}"
|
||||
# uncomment and change to branch name to run against
|
||||
# ref: some-branch
|
||||
# ref: show-aqua-version
|
||||
|
@ -18,15 +18,14 @@ use super::ExecutionCtx;
|
||||
use super::ExecutionResult;
|
||||
use super::TraceHandler;
|
||||
use crate::execution_step::boxed_value::CanonStream;
|
||||
use crate::execution_step::Generation;
|
||||
use crate::execution_step::Stream;
|
||||
use crate::log_instruction;
|
||||
use crate::trace_to_exec_err;
|
||||
use crate::ExecutionError;
|
||||
use crate::JValue;
|
||||
use crate::UncatchableError;
|
||||
|
||||
use air_interpreter_data::CanonResult;
|
||||
use air_interpreter_data::TracePos;
|
||||
use air_parser::ast;
|
||||
use air_trace_handler::merger::MergerCanonResult;
|
||||
|
||||
@ -39,8 +38,8 @@ impl<'i> super::ExecutableInstruction<'i> for ast::Canon<'i> {
|
||||
let canon_result = trace_to_exec_err!(trace_ctx.meet_canon_start(), self)?;
|
||||
|
||||
match canon_result {
|
||||
MergerCanonResult::CanonResult { stream_elements_pos } => {
|
||||
handle_seen_canon(self, stream_elements_pos, exec_ctx, trace_ctx)
|
||||
MergerCanonResult::CanonResult { canonicalized_element } => {
|
||||
handle_seen_canon(self, canonicalized_element, exec_ctx, trace_ctx)
|
||||
}
|
||||
MergerCanonResult::Empty => handle_unseen_canon(self, exec_ctx, trace_ctx),
|
||||
}
|
||||
@ -49,17 +48,22 @@ impl<'i> super::ExecutableInstruction<'i> for ast::Canon<'i> {
|
||||
|
||||
fn handle_seen_canon(
|
||||
ast_canon: &ast::Canon<'_>,
|
||||
stream_elements_pos: Vec<TracePos>,
|
||||
se_canon_stream: JValue,
|
||||
exec_ctx: &mut ExecutionCtx<'_>,
|
||||
trace_ctx: &mut TraceHandler,
|
||||
) -> ExecutionResult<()> {
|
||||
let canon_stream = create_canon_stream_from_pos(&stream_elements_pos, ast_canon, exec_ctx)?;
|
||||
let stream_with_positions = StreamWithPositions {
|
||||
let canon_stream = serde_json::from_value(se_canon_stream.clone()).map_err(|de_error| {
|
||||
ExecutionError::Uncatchable(UncatchableError::InvalidCanonStreamInData {
|
||||
canonicalized_stream: se_canon_stream.clone(),
|
||||
de_error,
|
||||
})
|
||||
})?;
|
||||
let canon_stream_with_se = StreamWithSerializedView {
|
||||
canon_stream,
|
||||
stream_elements_pos,
|
||||
se_canon_stream,
|
||||
};
|
||||
|
||||
epilog(ast_canon.canon_stream.name, stream_with_positions, exec_ctx, trace_ctx)
|
||||
epilog(ast_canon.canon_stream.name, canon_stream_with_se, exec_ctx, trace_ctx)
|
||||
}
|
||||
|
||||
fn handle_unseen_canon(
|
||||
@ -85,72 +89,43 @@ fn handle_unseen_canon(
|
||||
epilog(ast_canon.canon_stream.name, stream_with_positions, exec_ctx, trace_ctx)
|
||||
}
|
||||
|
||||
fn create_canon_stream_from_pos(
|
||||
stream_elements_pos: &[TracePos],
|
||||
ast_canon: &ast::Canon<'_>,
|
||||
exec_ctx: &ExecutionCtx<'_>,
|
||||
) -> ExecutionResult<CanonStream> {
|
||||
let stream = get_stream_or_default(ast_canon, exec_ctx);
|
||||
|
||||
let values = stream_elements_pos
|
||||
.iter()
|
||||
.map(|&position| {
|
||||
stream
|
||||
.get_value_by_pos(position)
|
||||
.ok_or(ExecutionError::Uncatchable(UncatchableError::VariableNotFoundByPos(
|
||||
position,
|
||||
)))
|
||||
.cloned()
|
||||
})
|
||||
.collect::<Result<Vec<_>, _>>()?;
|
||||
|
||||
let peer_id = crate::execution_step::air::resolve_to_string(&ast_canon.peer_pk, exec_ctx)?;
|
||||
let canon_stream = CanonStream::new(values, peer_id);
|
||||
Ok(canon_stream)
|
||||
}
|
||||
|
||||
fn epilog(
|
||||
canon_stream_name: &str,
|
||||
stream_with_positions: StreamWithPositions,
|
||||
stream_with_positions: StreamWithSerializedView,
|
||||
exec_ctx: &mut ExecutionCtx<'_>,
|
||||
trace_ctx: &mut TraceHandler,
|
||||
) -> ExecutionResult<()> {
|
||||
let StreamWithPositions {
|
||||
let StreamWithSerializedView {
|
||||
canon_stream,
|
||||
stream_elements_pos,
|
||||
se_canon_stream,
|
||||
} = stream_with_positions;
|
||||
|
||||
exec_ctx
|
||||
.scalars
|
||||
.set_canon_value(canon_stream_name, canon_stream)
|
||||
.map(|_| ())?;
|
||||
trace_ctx.meet_canon_end(CanonResult::new(stream_elements_pos));
|
||||
trace_ctx.meet_canon_end(CanonResult::new(se_canon_stream));
|
||||
Ok(())
|
||||
}
|
||||
|
||||
struct StreamWithPositions {
|
||||
struct StreamWithSerializedView {
|
||||
canon_stream: CanonStream,
|
||||
stream_elements_pos: Vec<TracePos>,
|
||||
se_canon_stream: JValue,
|
||||
}
|
||||
|
||||
fn create_canon_stream_from_name(
|
||||
ast_canon: &ast::Canon<'_>,
|
||||
peer_id: String,
|
||||
exec_ctx: &ExecutionCtx<'_>,
|
||||
) -> ExecutionResult<StreamWithPositions> {
|
||||
) -> ExecutionResult<StreamWithSerializedView> {
|
||||
let stream = get_stream_or_default(ast_canon, exec_ctx);
|
||||
|
||||
let canon_stream = CanonStream::from_stream(stream.as_ref(), peer_id);
|
||||
let stream_elements_pos = stream
|
||||
.iter(Generation::Last)
|
||||
// it's always safe to iter over all generations
|
||||
.unwrap()
|
||||
.map(|value| value.trace_pos)
|
||||
.collect::<Vec<_>>();
|
||||
let se_canon_stream = serde_json::to_value(&canon_stream).expect("default serialized shouldn't fail");
|
||||
|
||||
let result = StreamWithPositions {
|
||||
let result = StreamWithSerializedView {
|
||||
canon_stream,
|
||||
stream_elements_pos,
|
||||
se_canon_stream,
|
||||
};
|
||||
|
||||
Ok(result)
|
||||
|
@ -20,12 +20,14 @@ use crate::execution_step::Generation;
|
||||
use crate::JValue;
|
||||
|
||||
use polyplets::SecurityTetraplet;
|
||||
use serde::Deserialize;
|
||||
use serde::Serialize;
|
||||
|
||||
use std::rc::Rc;
|
||||
|
||||
/// Canon stream is a value type lies between a scalar and a stream, it has the same algebra as
|
||||
/// scalars, and represent a stream fixed at some execution point.
|
||||
#[derive(Debug, Default, Clone)]
|
||||
#[derive(Debug, Default, Clone, Deserialize, Serialize)]
|
||||
pub struct CanonStream {
|
||||
values: Vec<ValueAggregate>,
|
||||
// tetraplet is needed to handle adding canon streams as a whole to a stream
|
||||
@ -33,15 +35,6 @@ pub struct CanonStream {
|
||||
}
|
||||
|
||||
impl CanonStream {
|
||||
pub(crate) fn new(values: Vec<ValueAggregate>, peer_pk: String) -> Self {
|
||||
// tetraplet is comprised only from peer_pk here
|
||||
let tetraplet = SecurityTetraplet::new(peer_pk, "", "", "");
|
||||
Self {
|
||||
values,
|
||||
tetraplet: Rc::new(tetraplet),
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) fn from_stream(stream: &Stream, peer_pk: String) -> Self {
|
||||
// it's always possible to iter over all generations of a stream
|
||||
let values = stream.iter(Generation::Last).unwrap().cloned().collect::<Vec<_>>();
|
||||
|
@ -156,6 +156,7 @@ impl Stream {
|
||||
Some(JValue::Array(jvalue_array))
|
||||
}
|
||||
|
||||
#[allow(dead_code)]
|
||||
pub(crate) fn get_value_by_pos(&self, position: TracePos) -> Option<&ValueAggregate> {
|
||||
let StreamValueLocation {
|
||||
generation,
|
||||
|
@ -14,6 +14,7 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
use crate::JValue;
|
||||
use crate::ToErrorCode;
|
||||
|
||||
use air_interpreter_data::TracePos;
|
||||
@ -83,6 +84,12 @@ pub enum UncatchableError {
|
||||
/// as a hard error.
|
||||
#[error("variable with position '{0}' wasn't defined during script execution")]
|
||||
VariableNotFoundByPos(TracePos),
|
||||
|
||||
#[error("can't deserialize stream {canonicalized_stream:?} with error: {de_error}")]
|
||||
InvalidCanonStreamInData {
|
||||
canonicalized_stream: JValue,
|
||||
de_error: serde_json::Error,
|
||||
},
|
||||
}
|
||||
|
||||
impl ToErrorCode for UncatchableError {
|
||||
|
@ -265,7 +265,9 @@ fn canon_with_empty_behaviour() {
|
||||
let expected_trace = vec![
|
||||
executed_state::par(1, 1),
|
||||
executed_state::request_sent_by(peer_2_id),
|
||||
executed_state::canon(vec![]),
|
||||
executed_state::canon(
|
||||
json!({"tetraplet": {"function_name": "", "json_path": "", "peer_pk": "peer_2_id", "service_id": ""}, "values": []}),
|
||||
),
|
||||
];
|
||||
|
||||
assert_eq!(actual_trace, expected_trace);
|
||||
|
@ -133,7 +133,12 @@ fn length_functor_for_canon_stream() {
|
||||
let expected_trace = vec![
|
||||
executed_state::ap(0),
|
||||
executed_state::ap(0),
|
||||
executed_state::canon(vec![0.into(), 1.into()]),
|
||||
executed_state::canon(
|
||||
json!({"tetraplet": {"function_name": "", "json_path": "", "peer_pk": "init_peer_id", "service_id": ""},
|
||||
"values": [{"result": 1, "tetraplet": {"function_name": "", "json_path": "", "peer_pk": "init_peer_id", "service_id": ""}, "trace_pos": 0},
|
||||
{"result": 1, "tetraplet": {"function_name": "", "json_path": "", "peer_pk": "init_peer_id", "service_id": ""}, "trace_pos": 1}
|
||||
]} ),
|
||||
),
|
||||
executed_state::scalar_number(2),
|
||||
];
|
||||
assert_eq!(actual_trace, expected_trace);
|
||||
@ -157,7 +162,12 @@ fn length_functor_for_empty_canon_stream() {
|
||||
let result = executor.execute_one(init_peer_id).unwrap();
|
||||
let actual_trace = trace_from_result(&result);
|
||||
|
||||
let expected_trace = vec![executed_state::canon(vec![]), executed_state::scalar_number(0)];
|
||||
let expected_trace = vec![
|
||||
executed_state::canon(
|
||||
json!({"tetraplet": {"function_name": "", "json_path": "", "peer_pk": "init_peer_id", "service_id": ""}, "values": []} ),
|
||||
),
|
||||
executed_state::scalar_number(0),
|
||||
];
|
||||
assert_eq!(actual_trace, expected_trace);
|
||||
}
|
||||
|
||||
|
@ -236,7 +236,11 @@ fn ap_canon_stream_with_lambda() {
|
||||
let expected_state = vec![
|
||||
executed_state::stream_number(0, 0),
|
||||
executed_state::stream_number(1, 1),
|
||||
executed_state::canon(vec![0.into(), 1.into()]),
|
||||
executed_state::canon(
|
||||
json!({"tetraplet": {"function_name": "", "json_path": "", "peer_pk": "vm_1_peer_id", "service_id": ""},
|
||||
"values": [{"result": 0, "tetraplet": {"function_name": "", "json_path": "", "peer_pk": "vm_1_peer_id", "service_id": ""}, "trace_pos": 0},
|
||||
{"result": 1, "tetraplet": {"function_name": "some_function_name", "json_path": "", "peer_pk": "vm_1_peer_id", "service_id": "some_service_name"}, "trace_pos": 1}]}),
|
||||
),
|
||||
executed_state::ap(0),
|
||||
executed_state::scalar(json!([1])),
|
||||
];
|
||||
@ -277,7 +281,11 @@ fn ap_canon_stream() {
|
||||
let expected_state = vec![
|
||||
executed_state::stream_number(0, 0),
|
||||
executed_state::stream_number(1, 1),
|
||||
executed_state::canon(vec![0.into(), 1.into()]),
|
||||
executed_state::canon(
|
||||
json!({"tetraplet": {"function_name": "", "json_path": "", "peer_pk": "vm_1_peer_id", "service_id": ""},
|
||||
"values": [{"result": 0, "tetraplet": {"function_name": "", "json_path": "", "peer_pk": "vm_1_peer_id", "service_id": ""}, "trace_pos": 0},
|
||||
{"result": 1, "tetraplet": {"function_name": "some_function_name", "json_path": "", "peer_pk": "vm_1_peer_id", "service_id": "some_service_name"}, "trace_pos": 1}]}),
|
||||
),
|
||||
executed_state::ap(0),
|
||||
executed_state::scalar(json!([[0, 1]])),
|
||||
];
|
||||
|
@ -18,7 +18,6 @@ use air_test_utils::prelude::*;
|
||||
|
||||
use fstrings::f;
|
||||
use fstrings::format_args_f;
|
||||
use pretty_assertions::assert_eq;
|
||||
|
||||
use std::ops::Deref;
|
||||
|
||||
@ -62,7 +61,14 @@ fn basic_canon() {
|
||||
let result = checked_call_vm!(vm, <_>::default(), script, "", result.data);
|
||||
let actual_state = &trace_from_result(&result)[6.into()];
|
||||
|
||||
let expected_state = executed_state::canon(vec![1.into(), 2.into(), 3.into(), 4.into(), 5.into()]);
|
||||
let expected_state = executed_state::canon(
|
||||
json!({"tetraplet": {"function_name": "", "json_path": "", "peer_pk": "A", "service_id": ""},
|
||||
"values": [{"result": "1", "tetraplet": {"function_name": "", "json_path": "", "peer_pk": "A", "service_id": ""}, "trace_pos": 1},
|
||||
{"result": "2", "tetraplet": {"function_name": "", "json_path": "", "peer_pk": "A", "service_id": ""}, "trace_pos": 2},
|
||||
{"result": "3", "tetraplet": {"function_name": "", "json_path": "", "peer_pk": "A", "service_id": ""}, "trace_pos": 3},
|
||||
{"result": "4", "tetraplet": {"function_name": "", "json_path": "", "peer_pk": "A", "service_id": ""}, "trace_pos": 4},
|
||||
{"result": "5", "tetraplet": {"function_name": "", "json_path": "", "peer_pk": "A", "service_id": ""}, "trace_pos": 5}]}),
|
||||
);
|
||||
assert_eq!(actual_state, &expected_state);
|
||||
}
|
||||
|
||||
@ -106,7 +112,11 @@ fn canon_fixes_stream_correct() {
|
||||
executed_state::stream_number(2, 0),
|
||||
executed_state::stream_number(3, 1),
|
||||
executed_state::scalar_number(4),
|
||||
executed_state::canon(vec![3.into(), 4.into()]),
|
||||
executed_state::canon(
|
||||
json!({"tetraplet": {"function_name": "", "json_path": "", "peer_pk": "peer_id_3", "service_id": ""},
|
||||
"values": [{"result": 2, "tetraplet": {"function_name": "", "json_path": "", "peer_pk": "peer_id_2", "service_id": ""}, "trace_pos": 3},
|
||||
{"result": 3, "tetraplet": {"function_name": "", "json_path": "", "peer_pk": "peer_id_3", "service_id": ""}, "trace_pos": 4}]}),
|
||||
),
|
||||
executed_state::par(1, 1),
|
||||
executed_state::scalar(json!([2, 3])),
|
||||
executed_state::request_sent_by(peer_id_3),
|
||||
@ -122,7 +132,11 @@ fn canon_fixes_stream_correct() {
|
||||
executed_state::stream_number(2, 1),
|
||||
executed_state::stream_number(3, 2),
|
||||
executed_state::scalar_number(4),
|
||||
executed_state::canon(vec![3.into(), 4.into()]),
|
||||
executed_state::canon(
|
||||
json!({"tetraplet": {"function_name": "", "json_path": "", "peer_pk": "peer_id_3", "service_id": ""},
|
||||
"values": [{"result": 2, "tetraplet": {"function_name": "", "json_path": "", "peer_pk": "peer_id_2", "service_id": ""}, "trace_pos": 3},
|
||||
{"result": 3, "tetraplet": {"function_name": "", "json_path": "", "peer_pk": "peer_id_3", "service_id": ""}, "trace_pos": 4}]}),
|
||||
),
|
||||
executed_state::par(1, 1),
|
||||
executed_state::scalar(json!([2, 3])),
|
||||
executed_state::scalar(json!([2, 3])),
|
||||
@ -228,12 +242,22 @@ fn canon_empty_stream() {
|
||||
|
||||
let result = checked_call_vm!(vm_1, <_>::default(), &script, "", "");
|
||||
let actual_trace = trace_from_result(&result);
|
||||
let expected_trace = vec![executed_state::canon(vec![]), executed_state::scalar(json!([]))];
|
||||
let expected_trace = vec![
|
||||
executed_state::canon(
|
||||
json!({"tetraplet": {"function_name": "", "json_path": "", "peer_pk": "peer_id_1", "service_id": ""}, "values": []}),
|
||||
),
|
||||
executed_state::scalar(json!([])),
|
||||
];
|
||||
assert_eq!(actual_trace, expected_trace);
|
||||
|
||||
let result = checked_call_vm!(vm_2, <_>::default(), script, "", result.data);
|
||||
let actual_trace = trace_from_result(&result);
|
||||
let expected_trace = vec![executed_state::canon(vec![]), executed_state::scalar(json!([]))];
|
||||
let expected_trace = vec![
|
||||
executed_state::canon(
|
||||
json!({"tetraplet": {"function_name": "", "json_path": "", "peer_pk": "peer_id_1", "service_id": ""}, "values": []} ),
|
||||
),
|
||||
executed_state::scalar(json!([])),
|
||||
];
|
||||
assert_eq!(actual_trace, expected_trace);
|
||||
}
|
||||
|
||||
@ -248,7 +272,9 @@ fn canon_empty_not_writable_stream() {
|
||||
|
||||
let result = checked_call_vm!(vm, <_>::default(), &script, "", "");
|
||||
let actual_trace = trace_from_result(&result);
|
||||
let expected_trace = vec![executed_state::canon(vec![])];
|
||||
let expected_trace = vec![executed_state::canon(
|
||||
json!({"tetraplet": {"function_name": "", "json_path": "", "peer_pk": "peer_id", "service_id": ""}, "values": []} ),
|
||||
)];
|
||||
assert_eq!(actual_trace, expected_trace);
|
||||
}
|
||||
|
||||
@ -281,7 +307,9 @@ fn canon_over_later_defined_stream() {
|
||||
let expected_trace = vec![
|
||||
executed_state::par(1, 2),
|
||||
executed_state::stream_number(1, 0),
|
||||
executed_state::canon(vec![]),
|
||||
executed_state::canon(
|
||||
json!({"tetraplet": {"function_name": "", "json_path": "", "peer_pk": "vm_peer_id_1", "service_id": ""},"values": []}),
|
||||
),
|
||||
executed_state::scalar(json!([])),
|
||||
];
|
||||
assert_eq!(actual_trace, expected_trace);
|
||||
|
@ -582,7 +582,9 @@ fn fold_scalar_seq_next_completes_with_null() {
|
||||
executed_state::stream(service_result.clone(), 0),
|
||||
executed_state::par(1, 0),
|
||||
executed_state::stream(service_result.clone(), 0),
|
||||
executed_state::canon(vec![]),
|
||||
executed_state::canon(
|
||||
json!({"tetraplet": {"function_name": "", "json_path": "", "peer_pk": "vm_peer_id", "service_id": ""}, "values": []}),
|
||||
),
|
||||
executed_state::scalar(service_result),
|
||||
];
|
||||
assert_eq!(actual_trace, expected_trace);
|
||||
|
@ -128,8 +128,7 @@ pub struct ApResult {
|
||||
#[derive(Debug, Default, Clone, PartialEq, Eq, Serialize, Deserialize)]
|
||||
#[serde(rename_all = "snake_case")]
|
||||
pub struct CanonResult {
|
||||
#[serde(rename = "ids")]
|
||||
pub stream_elements_pos: Vec<TracePos>,
|
||||
pub canonicalized_element: JValue,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
|
||||
|
@ -87,9 +87,9 @@ impl ApResult {
|
||||
}
|
||||
|
||||
impl CanonResult {
|
||||
pub fn new(stream_elements_pos: Vec<TracePos>) -> Self {
|
||||
pub fn new(canonicalized_element: JValue) -> Self {
|
||||
Self {
|
||||
stream_elements_pos,
|
||||
canonicalized_element,
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -129,8 +129,8 @@ impl std::fmt::Display for ExecutedState {
|
||||
Ap(ap) => {
|
||||
write!(f, "ap: _ -> {:?}", ap.res_generations)
|
||||
}
|
||||
Canon(canon) => {
|
||||
write!(f, "canon {:?}", canon.stream_elements_pos)
|
||||
Canon(_) => {
|
||||
write!(f, "canon [<object>]")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -137,7 +137,7 @@ pub fn ap(generation: u32) -> ExecutedState {
|
||||
ExecutedState::Ap(ap_result)
|
||||
}
|
||||
|
||||
pub fn canon(stream_elements_pos: Vec<TracePos>) -> ExecutedState {
|
||||
let canon_result = CanonResult::new(stream_elements_pos);
|
||||
pub fn canon(canonicalized_element: JValue) -> ExecutedState {
|
||||
let canon_result = CanonResult::new(canonicalized_element);
|
||||
ExecutedState::Canon(canon_result)
|
||||
}
|
||||
|
@ -17,7 +17,7 @@
|
||||
use super::*;
|
||||
use crate::merger::errors::CanonResultError;
|
||||
|
||||
use bimap::BiHashMap;
|
||||
use serde_json::Value as JValue;
|
||||
|
||||
const EXPECTED_STATE_NAME: &str = "canon";
|
||||
|
||||
@ -28,8 +28,7 @@ pub enum MergerCanonResult {
|
||||
|
||||
/// There was a state in at least one of the contexts. If there were two states in
|
||||
/// both contexts, they were successfully merged.
|
||||
/// Positions correspond to a new data trace.
|
||||
CanonResult { stream_elements_pos: Vec<TracePos> },
|
||||
CanonResult { canonicalized_element: JValue },
|
||||
}
|
||||
|
||||
pub(crate) fn try_merge_next_state_as_canon(data_keeper: &mut DataKeeper) -> MergeResult<MergerCanonResult> {
|
||||
@ -39,13 +38,9 @@ pub(crate) fn try_merge_next_state_as_canon(data_keeper: &mut DataKeeper) -> Mer
|
||||
let current_state = data_keeper.current_slider_mut().next_state();
|
||||
|
||||
match (prev_state, current_state) {
|
||||
(Some(Canon(prev_canon)), Some(Canon(current_canon))) => {
|
||||
prepare_both_canon_result(&prev_canon, ¤t_canon, data_keeper)
|
||||
}
|
||||
(Some(Canon(prev_canon)), None) => prepare_single_canon_result(&prev_canon, &data_keeper.new_to_prev_pos),
|
||||
(None, Some(Canon(current_canon))) => {
|
||||
prepare_single_canon_result(¤t_canon, &data_keeper.new_to_current_pos)
|
||||
}
|
||||
(Some(Canon(prev_canon)), Some(Canon(current_canon))) => prepare_both_canon_result(prev_canon, ¤t_canon),
|
||||
(Some(Canon(prev_canon)), None) => prepare_single_canon_result(prev_canon),
|
||||
(None, Some(Canon(current_canon))) => prepare_single_canon_result(current_canon),
|
||||
(None, None) => Ok(MergerCanonResult::Empty),
|
||||
(prev_state, current_state) => Err(MergeError::incompatible_states(
|
||||
prev_state,
|
||||
@ -56,78 +51,29 @@ pub(crate) fn try_merge_next_state_as_canon(data_keeper: &mut DataKeeper) -> Mer
|
||||
}
|
||||
|
||||
fn prepare_both_canon_result(
|
||||
prev_canon_result: &CanonResult,
|
||||
prev_canon_result: CanonResult,
|
||||
current_canon_result: &CanonResult,
|
||||
data_keeper: &DataKeeper,
|
||||
) -> MergeResult<MergerCanonResult> {
|
||||
check_canon_results(prev_canon_result, current_canon_result, data_keeper)
|
||||
.map_err(MergeError::IncorrectCanonResult)?;
|
||||
prepare_single_canon_result(prev_canon_result, &data_keeper.new_to_prev_pos)
|
||||
check_canon_results(&prev_canon_result, current_canon_result).map_err(MergeError::IncorrectCanonResult)?;
|
||||
prepare_single_canon_result(prev_canon_result)
|
||||
}
|
||||
|
||||
fn prepare_single_canon_result(
|
||||
canon_result: &CanonResult,
|
||||
new_to_other_pos: &BiHashMap<TracePos, TracePos>,
|
||||
) -> MergeResult<MergerCanonResult> {
|
||||
let new_positions = canon_result
|
||||
.stream_elements_pos
|
||||
.iter()
|
||||
.map(|pos| {
|
||||
new_to_other_pos
|
||||
.get_by_right(pos)
|
||||
.cloned()
|
||||
.ok_or_else(|| CanonResultError::not_met_position(canon_result.clone(), *pos))
|
||||
})
|
||||
.collect::<Result<Vec<_>, _>>()?;
|
||||
|
||||
fn prepare_single_canon_result(canon_result: CanonResult) -> MergeResult<MergerCanonResult> {
|
||||
Ok(MergerCanonResult::CanonResult {
|
||||
stream_elements_pos: new_positions,
|
||||
canonicalized_element: canon_result.canonicalized_element,
|
||||
})
|
||||
}
|
||||
|
||||
fn check_canon_results(
|
||||
prev_canon_result: &CanonResult,
|
||||
current_canon_result: &CanonResult,
|
||||
data_keeper: &DataKeeper,
|
||||
) -> Result<(), CanonResultError> {
|
||||
if prev_canon_result.stream_elements_pos.len() != current_canon_result.stream_elements_pos.len() {
|
||||
return Err(CanonResultError::different_lens(
|
||||
if prev_canon_result.canonicalized_element != current_canon_result.canonicalized_element {
|
||||
return Err(CanonResultError::incompatible_state(
|
||||
prev_canon_result.clone(),
|
||||
current_canon_result.clone(),
|
||||
));
|
||||
}
|
||||
|
||||
let prev_slider = data_keeper.prev_slider();
|
||||
let current_slider = data_keeper.current_slider();
|
||||
for (position, (prev_idx, current_idx)) in prev_canon_result
|
||||
.stream_elements_pos
|
||||
.iter()
|
||||
.zip(current_canon_result.stream_elements_pos.iter())
|
||||
.enumerate()
|
||||
{
|
||||
let prev_state = prev_slider.state_at_position(*prev_idx);
|
||||
let current_state = current_slider.state_at_position(*current_idx);
|
||||
|
||||
match (prev_state, current_state) {
|
||||
(Some(ExecutedState::Call(prev_call_result)), Some(ExecutedState::Call(current_call_result)))
|
||||
if prev_call_result == current_call_result =>
|
||||
{
|
||||
continue;
|
||||
}
|
||||
(Some(ExecutedState::Ap(_)), Some(ExecutedState::Ap(_))) => {
|
||||
continue;
|
||||
}
|
||||
_ => {
|
||||
return Err(CanonResultError::incompatible_state(
|
||||
prev_canon_result.clone(),
|
||||
current_canon_result.clone(),
|
||||
prev_state.cloned(),
|
||||
current_state.cloned(),
|
||||
position,
|
||||
))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
@ -75,25 +75,10 @@ pub enum CallResultError {
|
||||
|
||||
#[derive(ThisError, Debug)]
|
||||
pub enum CanonResultError {
|
||||
#[error("canon results have different length: {prev_canon_result:?} != {current_canon_result:?}")]
|
||||
LensNotEqual {
|
||||
prev_canon_result: CanonResult,
|
||||
current_canon_result: CanonResult,
|
||||
},
|
||||
|
||||
#[error("canon results {prev_canon_result:?} {current_canon_result:?} at position {position} points to incompatible execution states: {prev_state:?} {current_state:?}")]
|
||||
#[error("canon results {prev_canon_result:?} {current_canon_result:?} points to incompatible execution states")]
|
||||
IncompatibleState {
|
||||
prev_canon_result: CanonResult,
|
||||
current_canon_result: CanonResult,
|
||||
prev_state: Option<ExecutedState>,
|
||||
current_state: Option<ExecutedState>,
|
||||
position: usize,
|
||||
},
|
||||
|
||||
#[error("position {position} from canon result {canon_result:?} hasn't been met yet")]
|
||||
NotMetPosition {
|
||||
canon_result: CanonResult,
|
||||
position: TracePos,
|
||||
},
|
||||
}
|
||||
|
||||
@ -155,32 +140,12 @@ impl CallResultError {
|
||||
}
|
||||
|
||||
impl CanonResultError {
|
||||
pub(crate) fn different_lens(prev_canon_result: CanonResult, current_canon_result: CanonResult) -> Self {
|
||||
Self::LensNotEqual {
|
||||
prev_canon_result,
|
||||
current_canon_result,
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) fn incompatible_state(
|
||||
prev_canon_result: CanonResult,
|
||||
current_canon_result: CanonResult,
|
||||
prev_state: Option<ExecutedState>,
|
||||
current_state: Option<ExecutedState>,
|
||||
position: usize,
|
||||
) -> Self {
|
||||
pub(crate) fn incompatible_state(prev_canon_result: CanonResult, current_canon_result: CanonResult) -> Self {
|
||||
Self::IncompatibleState {
|
||||
prev_canon_result,
|
||||
current_canon_result,
|
||||
prev_state,
|
||||
current_state,
|
||||
position,
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) fn not_met_position(canon_result: CanonResult, position: TracePos) -> Self {
|
||||
Self::NotMetPosition { canon_result, position }
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone, Copy, Debug)]
|
||||
|
Loading…
x
Reference in New Issue
Block a user