$signals Tokenizer output. */ public function validate( array $signals ): void { if ( array( 'occurrences', 'signal_types', 'symbols', 'syntax_state', 'truncated' ) !== $this->sorted_keys( $signals ) ) { throw new InvalidArgumentException( 'invalid_code_signal_shape' ); } if ( ! is_array( $signals['signal_types'] ) || ! is_array( $signals['occurrences'] ) || ! is_array( $signals['symbols'] ) || ! is_bool( $signals['truncated'] ) || ! in_array( $signals['syntax_state'], array( 'parsed', 'invalid', 'lexed', 'metadata' ), true ) ) { throw new InvalidArgumentException( 'invalid_code_signal_value' ); } if ( count( $signals['occurrences'] ) > self::MAX_OCCURRENCES || count( $signals['symbols'] ) > self::MAX_SYMBOLS ) { throw new InvalidArgumentException( 'code_signal_budget_exceeded' ); } foreach ( $signals['signal_types'] as $type ) { $this->assert_signal_type( $type ); } foreach ( $signals['occurrences'] as $occurrence ) { if ( ! is_array( $occurrence ) || array( 'line', 'marker', 'type' ) !== $this->sorted_keys( $occurrence ) || ! is_int( $occurrence['line'] ) || $occurrence['line'] < 1 || $occurrence['line'] > 10000000 || ! is_string( $occurrence['marker'] ) || 1 !== preg_match( '/^[a-z0-9][a-z0-9_-]{0,47}$/', $occurrence['marker'] ) ) { throw new InvalidArgumentException( 'invalid_code_occurrence' ); } $this->assert_signal_type( $occurrence['type'] ); } foreach ( $signals['symbols'] as $symbol ) { if ( ! is_array( $symbol ) || array( 'kind', 'line', 'symbol_hash' ) !== $this->sorted_keys( $symbol ) || ! is_string( $symbol['symbol_hash'] ) || 1 !== preg_match( '/^[a-f0-9]{64}$/', $symbol['symbol_hash'] ) || ! in_array( $symbol['kind'], array( 'function', 'class', 'interface', 'trait', 'enum' ), true ) || ! is_int( $symbol['line'] ) || $symbol['line'] < 1 || $symbol['line'] > 10000000 ) { throw new InvalidArgumentException( 'invalid_code_symbol' ); } } } /** @param mixed $type Signal identifier. */ private function assert_signal_type( $type ): void { if ( ! is_string( $type ) || 1 !== preg_match( '/^(?:syntax|compat|io|database|dynamic|filesystem|outbound|secret|hot|frontend|metadata)\.[a-z][a-z0-9_]{1,47}$/', $type ) ) { throw new InvalidArgumentException( 'unsafe_code_signal_type' ); } } /** * @param array $value Associative array. * @return list */ private function sorted_keys( array $value ): array { $keys = array_keys( $value ); sort( $keys, SORT_STRING ); return $keys; } }