protected function wrap( StorageInterface $input, array $definition ) {
    foreach( $definition as $property => $class ) {

      // wrap the whole value in a class, or every subvalue
      $is_array = $class{0} == '[' && $class{1} == ']';
      /** @var self $class */
      $class = ltrim( $class, '[]' );

      // choose between wrap modes
      $value = $input[ $property ];
      if( !class_exists( $class ) || !is_subclass_of( $class, self::class ) ) $input[ $property ] = null;
      else if( !$is_array ) $input[ $property ] = $class::instance( $value );
      else {

        $list = [];
        if( Collection::is( $value, true ) ) {
          foreach( $value as $i => $t ) {
            $list[ $i ] = $class::instance( $t );
          }
        }

        $input[ $property ] = $list;
      }
    }
  }