/**
  * is the variable a data container that we can read from?
  *
  * @param  mixed $item
  *         the item to check
  * @return boolean
  *         TRUE if the item is a data container
  *         FALSE otherwise
  */
 public static function check($item)
 {
     if (IsAssignable::check($item) || IsIndexable::check($item)) {
         return true;
     }
     return false;
 }
 /**
  * throws exceptions if $item is not an indexable data type
  *
  * @param  mixed $item
  *         the container to check
  * @param  string $exception
  *         the class to use when throwing an exception
  * @return void
  */
 public static function check($item, $exception = E4xx_UnsupportedType::class)
 {
     // make sure we have a string
     if (!IsIndexable::check($item)) {
         throw new $exception(SimpleType::from($item));
     }
 }
 /**
  * does it make sense to attempt to merge the contents of $theirs into
  * $ours?
  *
  * @param  mixed $ours
  *         where we want to merge to
  * @param  mixed $theirs
  *         where we want to merge from
  * @return boolean
  *         true if merging makes sense
  *         false otherwise
  */
 public static function into($ours, $theirs)
 {
     // we can't merge non-arrays, non-objects
     if (!IsTraversable::check($theirs) && !IsAssignable::check($theirs)) {
         return false;
     }
     // if we have arrays or databag-type objects, we're good
     if (IsIndexable::check($ours) || IsAssignable::check($ours)) {
         return true;
     }
     // if we get here, then $ours is a complex object, which
     // we do not know how to merge
     //
     // or it is a scalar, which doesn't support merging at all
     return false;
 }
 /**
  * merge their data into one of our data's properties
  *
  * @param  mixed $ours
  *         the data that we want to merge into
  * @param  string $property
  *         the property to merge into
  * @param  mixed $value
  *         the data that we want to merge from
  * @return void
  */
 public static function of(&$ours, $property, $value)
 {
     if (IsIndexable::check($ours)) {
         return self::ofArray($ours, $property, $value);
     }
     if (IsAssignable::check($ours)) {
         return self::ofObject($ours, $property, $value);
     }
     throw new E4xx_UnsupportedType(SimpleType::from($ours));
 }
 /**
  * merge their data into our data, using dot.notation.support to
  * find the point where the merge starts
  *
  * @param  object $ours
  *         the object that we want to merge into
  * @param  string $path
  *         the dot.notation.support path to where the merge should start
  * @param  mixed $value
  *         the data that we want to merge from
  * @param  array|callable|string|null
  *         if $path goes beyond what exists in $ours, how do we want to
  *         extend $ours?
  * @return void
  */
 public static function into(&$ours, $path, $value, $extendingItem = null)
 {
     if (IsAssignable::check($ours)) {
         return self::intoObject($ours, $path, $value, $extendingItem);
     }
     if (IsIndexable::check($ours)) {
         return self::intoArray($ours, $path, $value, $extendingItem);
     }
     throw new E4xx_UnsupportedType(SimpleType::from($ours));
 }
 /**
  * merge a single key into our object
  *
  * @param  object $ours
  *         the object to merge into
  * @param  mixed $key
  *         the array key to merge into
  * @param  mixed $value
  *         the data to merge in
  * @return void
  */
 private static function mergeKeyIntoAssignable($ours, $key, $value)
 {
     // general case - overwrite because merging isn't possible
     if (ShouldOverwrite::intoObject($ours, $key, $value)) {
         $ours->{$key} = $value;
         return;
     }
     // special case - we are merging into an array
     if (IsIndexable::check($ours->{$key})) {
         MergeIntoIndexable::from($ours->{$key}, $value);
         return;
     }
     // at this point, we are merging into an object, using recursion
     // for which I am going to hell
     MergeIntoAssignable::from($ours->{$key}, $value);
 }
 /**
  * should we overwrite $ours[$key] with the value of $theirs?
  *
  * @param  array $ours
  *         the array where $key may exist
  * @param  string $key
  *         the index on $ours whose fate we are deciding
  * @param  mixed $theirs
  *         the data we want to assign to the index
  * @return boolean
  *         TRUE if we should overwrite the index's existing value
  *         with $value
  *         TRUE if $key currently has no value
  *         FALSE if we should merge $value into the index's exist
  *         value
  */
 public static function intoArray($ours, $key, $theirs)
 {
     // robustness!
     if (!IsIndexable::check($ours)) {
         throw new E4xx_UnsupportedType(SimpleType::from($ours));
     }
     return self::checkArray($ours, $key, $theirs);
 }