| // Copyright 2026 The Chromium Authors. All rights reserved. | |
| // Use of this source code is governed by a BSD-style license that can be | |
| // found in the LICENSE file. | |
| #include "gn/ffi/session.h" | |
| #include <vector> | |
| #include "gn/build_settings.h" | |
| #include "gn/err.h" | |
| #include "gn/ffi/bridge.h" | |
| #include "gn/functions.h" | |
| #include "gn/parse_tree.h" | |
| #include "gn/scope.h" | |
| #include "gn/source_dir.h" | |
| #include "gn/tokenizer.h" | |
| struct Session; | |
| namespace { | |
| bool IsValidIdentifier(std::string_view str) { | |
| if (str.empty()) | |
| return false; | |
| if (!Tokenizer::IsIdentifierFirstChar(str[0])) | |
| return false; | |
| for (char c : str.substr(1)) { | |
| if (!Tokenizer::IsIdentifierContinuingChar(c)) | |
| return false; | |
| } | |
| return true; | |
| } | |
| } // namespace | |
| bool session_load(const Session& session, | |
| const Value& label, | |
| std::span<const Value> keys, | |
| Scope& dest_scope, | |
| ParseNodePtr parse_node, | |
| Err& err) { | |
| if (label.type() != Value::STRING) { | |
| err = Err(label.origin(), "Invalid load path.", | |
| "First argument to load must be a string corresponding to the " | |
| "label for the file to load."); | |
| return false; | |
| } | |
| std::string_view label_str = label.string_value(); | |
| if (!label_str.ends_with(".scl")) { | |
| err = Err(label.origin(), "The file to load must be a '.scl' file."); | |
| return false; | |
| } | |
| std::vector<rust::Str> keys_slice; | |
| keys_slice.reserve(keys.size()); | |
| for (const auto& key : keys) { | |
| if (key.type() != Value::STRING) { | |
| err = Err(key.origin(), "Invalid variable to load.", | |
| "Arguments to load must be strings."); | |
| return false; | |
| } | |
| std::string_view val_str = key.string_value(); | |
| if (!IsValidIdentifier(val_str)) { | |
| err = Err(key.origin(), "Invalid variable to load.", | |
| "Arguments to load must be valid identifiers."); | |
| return false; | |
| } | |
| keys_slice.push_back(rust::Str(StringAtom(val_str).str())); | |
| } | |
| session.load_values( | |
| rust::Str(label.string_value()), | |
| rust::Str(dest_scope.GetSourceDir().SourceWithNoTrailingSlash()), | |
| rust::Slice<const rust::Str>(keys_slice), dest_scope, | |
| *dest_scope.settings(), parse_node, err); | |
| return !err.has_error(); | |
| } |