/**
  * 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 assignable 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 (!IsAssignable::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 our array
  *
  * @param  array &$ours
  *         the array that we want to merge into
  * @param  array|object $theirs
  *         the data that we want to merge from
  * @return void
  */
 public static function from(&$ours, $theirs)
 {
     if (IsAssignable::check($theirs)) {
         return self::fromObject($ours, $theirs);
     }
     if (IsTraversable::check($theirs)) {
         return self::fromArray($ours, $theirs);
     }
     // at this point, we want to append onto the end of $ours
     $ours[] = $theirs;
 }
 /**
  * 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));
 }
 /**
  * extract a value from a container, using dot.notation.support
  *
  * @param  mixed $item
  *         the container to extract from
  * @param  string $path
  *         the dot.notation.support path to walk
  * @return mixed
  *         whatever we find when we walk the path
  */
 public static function from($item, $path)
 {
     // robustness!
     RequireReadableContainer::check($item, E4xx_UnsupportedType::class);
     if (IsAssignable::check($item)) {
         return self::fromObject($item, $path);
     }
     return self::fromArray($item, $path);
 }
 /**
  * get a child from part of our container tree, optionally extending
  * the container if needed
  *
  * @param  array|object &$container
  *         the container we want to get the child from
  * @param  string $part
  *         the name of the child that we want
  * @param  array|callable|string|null $extendingItem
  *         if we need to extend the container, this is what we use to
  *         do the extension
  * @return mixed
  */
 private static function &getChildFromPart(&$container, $part, $extendingItem = null)
 {
     if (IsAssignable::check($container)) {
         return self::getPartFromObject($container, $part, $extendingItem);
     }
     // if we get here, this must be an array
     $retval =& self::getPartFromArray($container, $part, $extendingItem);
     return $retval;
 }
 /**
  * merge their data into our object
  *
  * @param  object $ours
  *         the object that we want to merge into
  * @param  array|object $theirs
  *         the data that we want to merge from
  * @return void
  */
 public static function from($ours, $theirs)
 {
     if (IsAssignable::check($theirs)) {
         return self::fromObject($ours, $theirs);
     }
     if (IsTraversable::check($theirs)) {
         return self::fromArray($ours, $theirs);
     }
     // cannot merge anything that reaches here!
     throw new E4xx_UnsupportedType(SimpleType::from($ours));
 }
 /**
  * should we overwrite $ours->$property with the value of $theirs?
  *
  * @param  object $ours
  *         the object where $property may exist
  * @param  string $property
  *         the property on $ours whose fate we are deciding
  * @param  mixed $theirs
  *         the data we want to assign to the property
  * @return boolean
  *         TRUE if we should overwrite the property's existing value
  *         with $value
  *         TRUE if $property currently has no value
  *         FALSE if we should merge $value into the property's exist
  *         value
  */
 public static function intoObject($ours, $property, $theirs)
 {
     // robustness!
     if (!IsAssignable::check($ours)) {
         throw new E4xx_UnsupportedType(SimpleType::from($ours));
     }
     return self::checkObject($ours, $property, $theirs);
 }