blob: b2329bfb3e02577036d71cc0ce09905fb7b6f042 [file]
// 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();
}