Skip to content

[V3] Directory Loading and Begin Implementing Lazy-Loading #460

@project-laguardia

Description

@project-laguardia

Problem:

As it stands, Dasel does not lazy load to any extent, which can cause performance issues for large datasets.

Solution (Getter-Setters):

Dasel already has groundwork implemented for dynamically-loading properties (implemented for orderedmaps) in model.Value:

  • dasel/model/value_map.go

    Lines 85 to 127 in 5ac2dab

    func (v *Value) GetMapKey(key string) (*Value, error) {
    switch {
    case v.isDencodingMap():
    m, err := v.dencodingMapValue()
    if err != nil {
    return nil, fmt.Errorf("error getting map: %w", err)
    }
    val, ok := m.Get(key)
    if !ok {
    return nil, MapKeyNotFound{Key: key}
    }
    res := NewValue(val)
    res.setFn = func(newValue *Value) error {
    m.Set(key, newValue.Value.Interface())
    return nil
    }
    return res, nil
    case v.isStandardMap():
    unpacked, err := v.UnpackUntilKind(reflect.Map)
    if err != nil {
    return nil, fmt.Errorf("error unpacking value: %w", err)
    }
    i := unpacked.Value.MapIndex(reflect.ValueOf(key))
    if !i.IsValid() {
    return nil, MapKeyNotFound{Key: key}
    }
    res := NewValue(i)
    res.setFn = func(newValue *Value) error {
    mapRv, err := v.UnpackUntilKind(reflect.Map)
    if err != nil {
    return fmt.Errorf("error unpacking value: %w", err)
    }
    mapRv.Value.SetMapIndex(reflect.ValueOf(key), newValue.Value)
    return nil
    }
    return res, nil
    default:
    return nil, ErrUnexpectedType{
    Expected: TypeMap,
    Actual: v.Type(),
    }
    }
    }
  • dasel/model/value_map.go

    Lines 41 to 60 in 5ac2dab

    func (v *Value) SetMapKey(key string, value *Value) error {
    switch {
    case v.isDencodingMap():
    m, err := v.dencodingMapValue()
    if err != nil {
    return fmt.Errorf("error getting map: %w", err)
    }
    m.Set(key, value.Value.Interface())
    return nil
    case v.isStandardMap():
    unpacked, err := v.UnpackUntilKind(reflect.Map)
    if err != nil {
    return fmt.Errorf("error unpacking value: %w", err)
    }
    unpacked.Value.SetMapIndex(reflect.ValueOf(key), value.Value)
    return nil
    default:
    return fmt.Errorf("value is not a map")
    }
    }

Using this existing getter-setter structure, you could add support for lazily-loaded types that only load into memory on demand.

Use Case: Directory Loading

A simplistic first use-case would be directory loading. When parsing the directory, you first only load the directory tree into memory as a map. Then when leaves (files) are accessed, you load those on demand. This would give you a poor man's lazy-loading method for large datasets by allowing end users to segment their files.

Metadata

Metadata

Assignees

No one assigned

    Labels

    enhancementNew feature or request

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions