...

Source file src/edge-infra.dev/pkg/sds/display/k8s/apis/v2/displayconfig_merge.go

Documentation: edge-infra.dev/pkg/sds/display/k8s/apis/v2

     1  //nolint:revive
     2  package v2
     3  
     4  import (
     5  	"reflect"
     6  	"slices"
     7  
     8  	"dario.cat/mergo"
     9  )
    10  
    11  var ignoreTypes = []reflect.Type{
    12  	// Ignore primary as we always overwrite primary when set.
    13  	reflect.TypeOf(Primary(true)),
    14  	// Ignore DisplayPort as we should always use the original value.
    15  	reflect.TypeOf(DisplayPort("")),
    16  	// Ignore MPID as we should always use the original value.
    17  	reflect.TypeOf(MPID("")),
    18  }
    19  
    20  // Merge B into A and return a new copy.
    21  //
    22  // We assume A is a valid display configuration, i.e. details all displays that are present
    23  // on the node, and only apply configuration from B when it matches displays in A.
    24  //
    25  // When a display is present in both A and B, the displays will be merged in the
    26  // result - see Display.Merge(Display) for more detail. If a display is present in A but
    27  // not in B, it will be added to the result without changes. If a display is present in B,
    28  // but not A it will not be added to the result.
    29  //
    30  // The Layout from B will be merged into A. Only displays in B also present in A will be
    31  // respected. See Layout.Merge(Layout) for more detail.
    32  func (a *DisplayConfig) Merge(b *DisplayConfig) (*DisplayConfig, error) {
    33  	if b == nil {
    34  		return a, nil
    35  	}
    36  
    37  	result := a.DeepCopy()
    38  
    39  	displays, err := result.Displays.Merge(b.Displays)
    40  	if err != nil {
    41  		return nil, err
    42  	}
    43  	result.Displays = displays
    44  
    45  	// Merge DPMS, see DPMS.Merge(DPMS) for more detail.
    46  	dpms, err := result.DPMS.Merge(b.DPMS)
    47  	if err != nil {
    48  		return nil, err
    49  	}
    50  	result.DPMS = dpms
    51  
    52  	// Merge Layout, see Layout.Merge(Layout) for more detail.
    53  	result.Layout = result.Layout.Merge(b.Layout)
    54  
    55  	return result, nil
    56  }
    57  
    58  func (a Displays) Merge(b Displays) (Displays, error) {
    59  	result := a.DeepCopy()
    60  
    61  	// Merge displays that are present in both A and B
    62  	// see Display.Merge(Display) for more detail.
    63  	for _, bDisplay := range b {
    64  		if aDisplay := result.FindByDisplayPort(bDisplay.DisplayPort); aDisplay != nil {
    65  			display, err := aDisplay.Merge(bDisplay)
    66  			if err != nil {
    67  				return nil, err
    68  			}
    69  			result.UpdateDisplay(*display)
    70  		}
    71  	}
    72  
    73  	result = mergePrimaries(result, b)
    74  
    75  	return result, nil
    76  }
    77  
    78  // If primary has been set in B for a display also present in A,
    79  // the primary display will be updated in A to that in B.
    80  func mergePrimaries(a, b Displays) Displays {
    81  	result := a.DeepCopy()
    82  
    83  	// check if primary is set in B for any of the displays in A
    84  	var primary DisplayPort
    85  	for _, aDisplay := range result {
    86  		dp := aDisplay.DisplayPort
    87  		if bDisplay := b.FindByDisplayPort(dp); bDisplay != nil {
    88  			if bDisplay.IsPrimary() {
    89  				primary = dp
    90  				break
    91  			}
    92  		}
    93  	}
    94  
    95  	// if we found a new primary, update the result
    96  	if primary != "" {
    97  		for _, display := range result {
    98  			if display.DisplayPort == primary {
    99  				display.SetPrimary(true)
   100  			} else if display.IsPrimary() {
   101  				display.SetPrimary(false)
   102  			}
   103  			result.UpdateDisplay(display)
   104  		}
   105  	}
   106  
   107  	return result
   108  }
   109  
   110  // Merge Display B into Display A and return a new copy.
   111  //
   112  // When a value is present in B set it in A, otherwise use the value from A.
   113  //
   114  // Input device mappings in b will always replace the mappings in a if the mappings
   115  // in B are not empty, i.e. mappings in B are not appended to those in A.
   116  func (a *Display) Merge(b Display) (*Display, error) {
   117  	base := a.DeepCopy()
   118  	overlay := b.DeepCopy()
   119  
   120  	if err := mergo.Merge(
   121  		base,
   122  		overlay,
   123  		mergo.WithOverride,
   124  		mergo.WithTransformers(t),
   125  	); err != nil {
   126  		return nil, err
   127  	}
   128  
   129  	return base, nil
   130  }
   131  
   132  func (a *DPMS) Merge(b *DPMS) (*DPMS, error) {
   133  	if a == nil {
   134  		return b, nil
   135  	} else if b == nil {
   136  		return a, nil
   137  	}
   138  
   139  	base := a.DeepCopy()
   140  	overlay := b.DeepCopy()
   141  
   142  	if err := mergo.Merge(
   143  		base,
   144  		overlay,
   145  		mergo.WithOverride,
   146  		mergo.WithTransformers(t),
   147  	); err != nil {
   148  		return nil, err
   149  	}
   150  
   151  	return base, nil
   152  }
   153  
   154  // Merge Layout B into Layout A and return a new copy.
   155  //
   156  // For each display in B present in A, we append to the result respecting the order
   157  // in B. For the remaining display in A not present in B, we append to the result
   158  // respecting the order in A.
   159  func (a Layout) Merge(b Layout) Layout {
   160  	if len(a) == 0 {
   161  		return a
   162  	}
   163  
   164  	result := Layout{}
   165  
   166  	// add each display in B that is present in A, respecting its order in B
   167  	for _, dp := range b {
   168  		if slices.Contains(a, dp) {
   169  			result = append(result, dp)
   170  		}
   171  	}
   172  
   173  	// add the remaining displays from A that were not in B, respecting its order in A
   174  	for _, dp := range a {
   175  		if !slices.Contains(result, dp) {
   176  			result = append(result, dp)
   177  		}
   178  	}
   179  
   180  	return result
   181  }
   182  

View as plain text