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

Feature: pre-serialize and post-deserialize callbacks #120

Open
alex-tee opened this issue Mar 7, 2020 · 6 comments
Open

Feature: pre-serialize and post-deserialize callbacks #120

alex-tee opened this issue Mar 7, 2020 · 6 comments

Comments

@alex-tee
Copy link

alex-tee commented Mar 7, 2020

It seems like it would be quite common to want to do some logic on a struct before serializing it or after deserializing it. one use case would be to fill in more information on the struct after deserializing it, another would be to "prepare" some data for serialization.

the user would register callbacks on serializable structs to be called either before cyaml starts serialization or after cyaml finished deserialization

this is kinda doable if you traverse all your structs and do it manually, but it would be nice if cyaml took care of it automatically for every struct it touches

@tlsa
Copy link
Owner

tlsa commented Mar 12, 2020

Can you give me an example use-case to think about?

Why would this be more useful than simply filling out your data structures before saving, or annotating them with extra info after loading?

@alex-tee
Copy link
Author

i use polymorphism in my code:

typedef struct UndoableAction
{
  UndoableActionType         type;
  int                        stack_idx;
} UndoableAction;

static const cyaml_schema_field_t
  undoable_action_fields_schema[] =
{
  CYAML_FIELD_ENUM (
    "type", CYAML_FLAG_DEFAULT,
    UndoableAction, type,
    undoable_action_type_strings,
    CYAML_ARRAY_LEN (undoable_action_type_strings)),
  YAML_FIELD_INT (
    UndoableAction, stack_idx),

  CYAML_FIELD_END
};

static const cyaml_schema_value_t
  undoable_action_schema =
{
  CYAML_VALUE_MAPPING (CYAML_FLAG_POINTER,
    UndoableAction, undoable_action_fields_schema),
};
typedef struct MoveTracksAction
{
  UndoableAction  parent_instance;
  int             pos;
  TracklistSelections * tls;
} MoveTracksAction;

static const cyaml_schema_field_t
  move_tracks_action_fields_schema[] =
{
  CYAML_FIELD_MAPPING (
    "parent_instance", CYAML_FLAG_DEFAULT,
    MoveTracksAction, parent_instance,
    undoable_action_fields_schema),
  CYAML_FIELD_MAPPING_PTR (
    "tls", CYAML_FLAG_POINTER,
    MoveTracksAction, tls,
    tracklist_selections_fields_schema),
  CYAML_FIELD_INT (
    "pos", CYAML_FLAG_DEFAULT,
    MoveTracksAction, pos),

  CYAML_FIELD_END
};

static const cyaml_schema_value_t
  move_tracks_action_schema =
{
  CYAML_VALUE_MAPPING (
    CYAML_FLAG_POINTER, MoveTracksAction,
    move_tracks_action_fields_schema),
};

Then I want to serialize my Undo history which consists of many UndoableAction's, but this is impossible to serialize, so I have something like this:

typedef struct UndoStack
{
  /** Actual stack used at runtime. */
  Stack *       stack;

  /* the following are for serialization
   * purposes only */

  ArrangerSelectionsAction ** as_actions;
  size_t        num_as_actions;
  size_t        as_actions_size;

  CopyPluginsAction ** copy_plugins_actions;
  size_t        num_copy_plugins_actions;
  size_t        copy_plugins_actions_size;

  CopyTracksAction ** copy_tracks_actions;
  size_t        num_copy_tracks_actions;
  size_t        copy_tracks_actions_size;

  CreatePluginsAction ** create_plugins_actions;
  size_t        num_create_plugins_actions;
  size_t        create_plugins_actions_size;

  CreateTracksAction ** create_tracks_actions;
  size_t        num_create_tracks_actions;
  size_t        create_tracks_actions_size;

  DeletePluginsAction ** delete_plugins_actions;
  size_t        num_delete_plugins_actions;
  size_t        delete_plugins_actions_size;

  DeleteTracksAction ** delete_tracks_actions;
  size_t        num_delete_tracks_actions;
  size_t        delete_tracks_actions_size;

  EditPluginsAction ** edit_plugins_actions;
  size_t        num_edit_plugins_actions;
  size_t        edit_plugins_actions_size;

  EditTracksAction ** edit_tracks_actions;
  size_t        num_edit_tracks_actions;
  size_t        edit_tracks_actions_size;

  MovePluginsAction ** move_plugins_actions;
  size_t        num_move_plugins_actions;
  size_t        move_plugins_actions_size;

  MoveTracksAction ** move_tracks_actions;
  size_t        num_move_tracks_actions;
  size_t        move_tracks_actions_size;

} UndoStack;

static const cyaml_schema_field_t
  undo_stack_fields_schema[] =
{
  YAML_FIELD_DYN_PTR_ARRAY_VAR_COUNT_OPTIONAL (
    UndoStack, as_actions,
    arranger_selections_action_schema),
  YAML_FIELD_DYN_PTR_ARRAY_VAR_COUNT_OPTIONAL (
    UndoStack, copy_plugins_actions,
    copy_plugins_action_schema),
  YAML_FIELD_DYN_PTR_ARRAY_VAR_COUNT_OPTIONAL (
    UndoStack, copy_tracks_actions,
    copy_tracks_action_schema),
  YAML_FIELD_DYN_PTR_ARRAY_VAR_COUNT_OPTIONAL (
    UndoStack, create_plugins_actions,
    create_plugins_action_schema),
  YAML_FIELD_DYN_PTR_ARRAY_VAR_COUNT_OPTIONAL (
    UndoStack, create_tracks_actions,
    create_tracks_action_schema),
  YAML_FIELD_DYN_PTR_ARRAY_VAR_COUNT_OPTIONAL (
    UndoStack, delete_plugins_actions,
    delete_plugins_action_schema),
  YAML_FIELD_DYN_PTR_ARRAY_VAR_COUNT_OPTIONAL (
    UndoStack, delete_tracks_actions,
    delete_tracks_action_schema),
  YAML_FIELD_DYN_PTR_ARRAY_VAR_COUNT_OPTIONAL (
    UndoStack, edit_plugins_actions,
    edit_plugins_action_schema),
  YAML_FIELD_DYN_PTR_ARRAY_VAR_COUNT_OPTIONAL (
    UndoStack, edit_tracks_actions,
    edit_tracks_action_schema),
  YAML_FIELD_DYN_PTR_ARRAY_VAR_COUNT_OPTIONAL (
    UndoStack, move_plugins_actions,
    move_plugins_action_schema),
  YAML_FIELD_DYN_PTR_ARRAY_VAR_COUNT_OPTIONAL (
    UndoStack, move_tracks_actions,
    move_tracks_action_schema),

  CYAML_FIELD_END
};

static const cyaml_schema_value_t
  undo_stack_schema =
{
  YAML_VALUE_PTR (
    UndoStack, undo_stack_fields_schema),
};

(the Stack contains a bunch of void pointers to undoable actions)

So right before saving, I need to traverse the stack and fill in each array in UndoStack, so the information can be serialized properly. Then, after loading, I need to fill in the stack again from these arrays.

Why would this be more useful than simply filling out your data structures before saving, or annotating them with extra info after loading?

Convenience. My project YAML is huge and complex so it means I need to traverse the parent struct and find and do this for all child structs that need it. I also could accidentally miss something. Registering a callback for a specific type of struct would ensure that it will be called.

I also understand that this could make libcyaml more complex than it needs to be so I'm not 100% sure if this feature should be added or not.

@elecpower
Copy link

I'm involved in an open source project which needs just this. Needs to convert text to internal and reverse and enum type is not suitable.

@tlsa
Copy link
Owner

tlsa commented May 15, 2022

Would support for unions handle this use case?

struct my_thing {
        enum my_type type;
        union my_data data;
};

@alex-tee
Copy link
Author

alex-tee commented May 15, 2022

Are you asking if supporting unions would implement this feature? I don't think so. How would unions help? For one, it may not be possible/desirable to change your structs. Also, the point of this feature request is:

  1. to add some dynamic logic for generating a value to save instead of saving something already stored in the struct
  2. to execute some other logic unrelated to saving/loading (like a notification callback)

@tlsa
Copy link
Owner

tlsa commented Jun 2, 2023

@alex-tee The validation callbacks on main now would effectively serve as post-deserialise callbacks.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants