File: rust/library/proc_macro/src/bridge/rpc.rs
在Rust源代码中,rust/library/proc_macro/src/bridge/rpc.rs文件的作用是实现了Rust编程语言的编译过程中的远程过程调用(RPC)机制。 这个文件定义了与编译器的交互过程中使用的各种数据结构和接口。
具体来说,UnknownPanicMessage结构是用于表示编译器返回的未知错误信息。它包含一个字符串字段,用于描述错误的详细信息。
Encode<S>
是一个trait,用于将数据结构编码为字节序列。这个trait是为了在编译器和Rust应用程序之间传输数据而设计的。
Decode<'a>是一个trait,用于将字节序列解码为数据结构。这个trait是用于在Rust应用程序中解析从编译器返回的数据。
DecodeMut<'a>是一个trait,类似于Decode<'a>,但它提供了对可变引用的支持,可以在解析过程中修改数据。
Tag是一个枚举,用于标识RPC消息的类型。它包含了各种不同的RPC消息类型,例如编译器请求、编译器响应等。
PanicMessage是一个枚举,用于表示编译器发生崩溃时返回的错误信息。它包含了各种不同的崩溃类型,例如崩溃的文件、崩溃的行号等。
总体而言,rpc.rs文件中的这些数据结构、trait和枚举类型定义了编译器和Rust应用程序之间进行远程过程调用所需的协议和通信方式。
File: rust/library/proc_macro/src/bridge/fxhash.rs
在Rust源代码中,rust/library/proc_macro/src/bridge/fxhash.rs文件是proc_macro库中的一个模块,主要提供了与哈希相关的功能。
该文件中定义了一个名为FxHasher的结构体实现。FxHasher是一个自定义的哈希器,它采用了一种叫做"Fowler-Noll-Vo" (FNV) 的哈希算法,该算法简单高效且拥有较低的冲突率。FxHasher结构体实现了std::hash::Hasher trait,并为proc_macro库中的其他结构体和函数提供了自定义哈希功能。
在FxHasher结构体定义下方,还定义了FxHasher32和FxHasher64两个新类型。它们都是FxHasher的别名,并具有不同的哈希输出位数。FxHasher32输出32位哈希值,FxHasher64输出64位哈希值。这样设计的目的是为了在不同的场景中提供不同位数的哈希功能,以满足不同的需求。
FxHasher结构体以及其衍生结构体FxHasher32和FxHasher64的作用是提供高性能的哈希功能。在proc_macro库中,这些哈希器主要用于优化内部的哈希计算,提供高效的数据存储和查找能力,从而提升整个库的性能。
总之,rust/library/proc_macro/src/bridge/fxhash.rs文件中的FxHasher结构体及其衍生类型主要用于实现自定义的哈希算法,为proc_macro库中的其他功能模块提供高效的哈希能力,从而提升整个库的性能。
File: rust/library/proc_macro/src/bridge/arena.rs
在Rust源代码中,rust/library/proc_macro/src/bridge/arena.rs文件的作用是提供一个用于分配内存的类型Arena。具体来说,它提供了三个struct:TypedArena、ArenaBox和ArenaSlice。
-
TypedArena: TypedArena是一个通用的分配器类型,它可以用来分配任意类型的对象。TypedArena具有方法:new()初始化一个新的TypedArena对象,alloc()分配一个对象的内存并返回一个可变引用,to_vec()将TypedArena中的对象转换为Vec。 TypedArena通过维护一个指向内部内存的指针,动态分配内存来存储这些对象。当TypedArena对象被销毁时,它会释放内部分配的所有内存。
-
ArenaBox: ArenaBox是一个简单的盒子类型,它用于在Arena中持有一个对象的所有权。它内部包含了一个指向它所在的Arena对象的引用以及对象本身。
-
ArenaSlice: ArenaSlice类似于Rust中的切片类型,它是一个对Arena中连续一段内存的引用。ArenaSlice包含了一个指向开始位置的指针和一个长度。与普通的切片不同,ArenaSlice不支持索引操作,只能用于迭代访问。
这些Arena类型主要用于提供高效的内存分配和管理机制,特别适用于需要频繁创建和销毁一些中间结果对象的场景。通过使用Arena,可以避免频繁的堆分配操作,从而提高性能并减少内存碎片。
File: rust/library/proc_macro/src/bridge/client.rs
在Rust源代码中,rust/library/proc_macro/src/bridge/client.rs文件的作用是提供与proc_macro相关的客户端功能。
-
HandleCounters: 这个struct用于跟踪客户端处理的数量。它包含两个计数器字段,一个用于跟踪处理的引用计数,另一个用于跟踪处理中断的计数。
-
HandleStore<S>
: 这个struct是一个处理存储器。它使用一个哈希映射来存储处理的状态,并提供一些方法用于管理处理的创建、查找和删除。 -
Bridge<'a>, Client: 这两个struct是proc_macro的客户端桥接和客户端的抽象。Bridge结构体用于管理与服务器的通信和处理的创建,Client结构体用于实际的处理的使用。
-
BridgeState<'a>: 这个枚举表示桥接器的状态。它可以有三种状态:未初始化、与服务器建立连接或与服务器断开连接。
-
BridgeStateL: 这个枚举表示桥接器的生命周期状态,即它可以是持久化状态,也可以是非持久化状态。持久化状态表示与服务器的连接是持久的,非持久化状态表示与服务器的连接是临时的。
-
ProcMacro: 这个枚举表示处理的类型。它有三种类型:函数、过程宏和属性宏。这些类型用于在处理创建时标识并在处理使用时进行区分。
总的来说,rust/library/proc_macro/src/bridge/client.rs文件中的这些struct和enum提供了与proc_macro相关的客户端功能,包括处理的管理和与服务器的通信。它们在调用处理期间进行处理的跟踪和存储,并提供了适当的抽象化和状态管理。
File: rust/library/proc_macro/src/bridge/handle.rs
文件的作用: rust/library/proc_macro/src/bridge/handle.rs文件是Rust编程语言中的库proc_macro的一部分,它提供了与过程宏相关的处理功能。该文件中的各个结构体和函数用于处理过程宏的句柄。
OwnedStore 结构体的作用: OwnedStore 结构体是一个持有句柄的数据结构,它用于存储特定类型的句柄,并提供了对这些句柄进行管理的功能。这个结构体具有如下功能:
-
存储和管理句柄对象。 -
提供创建和销毁句柄的方法。 -
提供查询句柄是否有效的方法。
InternedStore 结构体的作用: InternedStore 结构体也是一个持有句柄的数据结构,它与 OwnedStore 结构体相似,但有一些区别。该结构体用于存储无生命周期句柄的情况下,可以内部化和共享一些仅需要较少的副本的数据。这个结构体具有如下功能:
-
内部化数据,共享所需的句柄数据。 -
提供创建和销毁句柄的方法。 -
提供查询句柄是否有效的方法。
这两个结构体及其相关函数主要用于处理过程宏的句柄数据,通过存储和管理这些句柄,提供了对句柄的有效性检查和操作功能。
File: rust/library/proc_macro/src/bridge/symbol.rs
在Rust源代码中,rust/library/proc_macro/src/bridge/symbol.rs
文件的作用是提供符号(Symbols)相关的功能。该文件定义了Symbol(NonZeroU32)
和Interner
这两个结构体。
Symbol(NonZeroU32)
是一个包含非零u32
值的结构体。它用于表示一个唯一的符号,这些符号在编译期间被用作标识符、函数名、结构体名等。Symbol
结构体使用非零的u32
值来确保符号的唯一性,并且可以通过NonZeroU32
类型的功能进行数值操作。
Interner
结构体是一个用于管理和查询符号的内部数据结构。它维护了一个符号到整数的映射,允许在符号之间进行快速的查找和比较。Interner
结构体内部包含一个Vec<Symbol>
类型的集合,用于存储所有的符号。它还实现了一些方法,如get_or_intern()
用于获取或者插入一个符号,get()
用于根据整数索引获取对应的符号,resolve()
用于通过符号获取对应的整数索引。
这些结构体的作用是为了处理和管理编译期间的符号,并提供高效的符号操作。符号在编译器中非常重要,因为它们被用于标识和访问各种源代码中的元素。通过Symbol
和Interner
可以有效地管理和查询这些符号,以提高编译器的性能和效率。
File: rust/library/proc_macro/src/bridge/scoped_cell.rs
在Rust源代码中,scoped_cell.rs
文件的作用是实现了一个名为ScopedCell
的结构体,该结构体提供了一种将动态作用域包装的机制,以允许在一个作用域中非持久性地借用值。
首先,让我们来介绍一下ScopedCell
结构体的作用。ScopedCell
是一个使用引用计数(reference counting)的结构体,在编译时期通过代码生成来创建可变的借用。它允许在一个作用域中暂时地获取对某个值的持久借用,而不需要使用所有权。
下面是一些定义在scoped_cell.rs
中的重要结构体和特征:
-
RefMutL<'a, T: 'a>
:这是一个泛型结构体,用于表示一个在作用域中可变地借用一个值的引用。它使用了生命周期限定符'a
,以确保借用的生命周期不会超过作用域的范围。这个结构体实现了Deref
和DerefMut
特征,以允许对借用值进行解引用和修改。 -
ScopedCell<T: PutBackOnDrop<'a>>
:这是一个泛型结构体,用于包装一个值并提供对该值的借用。这个结构体具有几个方法,包括borrow_mut()
方法,它返回一个可变引用,并在作用域结束时将可变引用还回给ScopedCell
。 -
ApplyL<'a>
:这是一个特征,定义了一个apply()
方法,以将一个函数应用于RefMutL
的值。 -
LambdaL
:这是一个特征,定义了一个lambda()
方法,以创建一个闭包,并在RefMutL
的值上执行操作。
这些结构体和特征的组合使得ScopedCell
提供了一种动态作用域的机制,允许在一个作用域中临时地获取可变的借用,并在作用域结束时将借用的值返回给ScopedCell
。这对于某些特定的应用场景非常有用,比如需要通过共享数据结构进行并行计算。
希望以上详细的介绍对您有所帮助!
File: rust/library/proc_macro/src/bridge/closure.rs
rust/library/proc_macro/src/bridge/closure.rs
这个文件是Rust中的核心库提供的proc_macro
模块中的一个模块。proc_macro
模块用于实现和处理编译时宏(procedural macros)。
在这个文件中,有几个struct,分别是Closure
, <'a,Env>,
。下面逐个介绍它们的作用:
-
Closure
:这是一个代表闭包的结构体。定义如下:pub struct Closure<'a, Env> {
env: *mut Env,
state: &'a mut State,
}Closure
结构体有两个字段:-
env
:一个指向闭包环境的指针,它是一个原始指针类型。闭包环境是在创建闭包时捕获的变量集合,可以在闭包的执行过程中使用。这个指针允许在编译时宏的执行期间访问闭包环境中的值。 -
state
:一个可变引用,用于表示闭包的状态。在proc_macro
模块中,闭包经常被用来进行代码转换和处理。state
字段用于在闭包执行过程中保存和更新状态。
-
-
<'a, Env>
:这是一个泛型结构体,用于表示闭包环境的类型。在Closure
结构体中的Env
字段的类型就是由<'a, Env>
泛型参数决定的。这个结构体提供了一个泛型的接口,以便在编译时宏的执行过程中处理各种类型的闭包环境。
总的来说,Closure
结构体和相应的泛型结构体提供了一个在编译时宏中处理闭包的机制。这样可以在宏扩展期间操作和修改闭包的环境,并根据需要更新闭包的状态。这对于实现复杂的编译时转换和代码生成非常有用。
File: rust/library/proc_macro/src/bridge/selfless_reify.rs
在Rust源代码中,rust/library/proc_macro/src/bridge/selfless_reify.rs文件的作用是实现了与proc_macro自定义属性之间的通信桥梁。
Rust是一种静态强类型系统的编程语言,它提供了一种叫做"过程宏"(proc_macro)的功能,使开发者能够在编译时处理Rust代码的语法结构。proc_macro可以用于编写自定义属性、函数和类型,从而扩展Rust的语言能力。
selfless_reify.rs文件的主要目标是在过程宏和自定义属性之间建立通信机制。具体而言,它定义了一系列的数据结构和函数,这些数据结构和函数允许过程宏在收到来自自定义属性的请求时进行响应,并提供自定义属性所需的信息。
该文件中的关键结构体是SelflessReificationRequest和SelflessReificationResponse。SelflessReificationRequest代表了从自定义属性到过程宏的请求,其中包括Rust代码的抽象语法树(AST)以及所需的任何其他信息。SelflessReificationResponse代表了过程宏对请求的响应,其中包括生成的代码和其他相关的数据。
除了上述基本的数据结构外,selfless_reify.rs还定义了一些函数,用于处理和处理SelflessReificationRequest和SelflessReificationResponse之间的转换和序列化。这些函数使得过程宏和自定义属性能够有效地交换信息,以便有效地进行编译时代码转换和代码生成。
总的来说,rust/library/proc_macro/src/bridge/selfless_reify.rs文件的作用是实现了过程宏和自定义属性之间的通信协议,为proc_macro提供了与用户代码之间进行可靠交流的基础。它是Rust编译器中关键的工具之一,使得开发者能够轻松地编写和使用自定义属性和过程宏,提高代码的灵活性和可维护性。
File: rust/library/proc_macro/src/bridge/buffer.rs
在Rust源代码中,rust/library/proc_macro/src/bridge/buffer.rs文件的作用是实现用于处理Rust宏扩展中的输入和输出数据的缓冲区。
该文件中定义了几个结构体,分别是InputBuffer、OutputBuffer和OutputBufferMut。它们都是用于处理输入和输出数据的缓冲区。
-
InputBuffer:这个结构体用于表示输入数据的缓冲区,主要用于将Rust源代码中的输入数据转换为内部数据结构。它提供了一些方法,比如
consume
方法用于从缓冲区中读取指定数量的字节,并返回一个新的缓冲区;peek
方法用于返回缓冲区中的下一个字节,但不会将其从缓冲区中移除。通过这些方法,我们可以对输入数据进行逐渐的读取和解析。 -
OutputBuffer:这个结构体用于表示输出数据的缓冲区,主要用于将宏扩展的输出数据序列化为字节流。它提供了一些方法,比如
write
用于将一段字节流写入缓冲区;advance
用于向前移动缓冲区的写入位置;position
用于返回当前的写入位置。通过这些方法,我们可以将输出数据逐渐地写入缓冲区。 -
OutputBufferMut:这个结构体与OutputBuffer功能类似,但是它是可变的。它提供了一些额外的方法,比如
current_slice_mut
用于返回当前写入位置的可变引用;ensure_capacity
用于确保缓冲区的容量足够存储指定数量的字节。通过这些方法,我们可以直接修改输出数据的内容,并确保缓冲区的容量始终足够。
这些缓冲区结构体在宏扩展期间起到了关键的作用,它们帮助我们处理输入和输出数据的转换和序列化,并提供了一些方便的方法来操作这些数据。这使得我们可以更方便地开发和调试Rust宏扩展。
File: rust/library/proc_macro/src/bridge/server.rs
文件rust/library/proc_macro/src/bridge/server.rs
的作用是实现proc_macro服务器的桥接。
在该文件中,MarkedTypes
定义了一系列类型,包括了Dispatcher
、RunningSameThreadGuard
、MaybeCrossThread
、SameThread
和CrossThread
。其作用是根据传入的参数来选择具体的执行策略。
-
Dispatcher
是一个派发器,负责将请求分发给不同的进程或线程。 -
RunningSameThreadGuard
是一个占位结构,用于协助确定执行策略。 -
MaybeCrossThread
和SameThread
分别表示了可能的跨线程和同线程执行的策略。 -
CrossThread
使用PhantomData
标记了跨线程执行。
而Types
和$name
是在宏展开中使用的占位符。
Server
是服务器的实现,负责接收请求并将其分发给派发器进行处理。
DispatcherTrait
是一个trait,定义了派发器的接口,包括收发消息和执行策略的选择。
ExecutionStrategy
是一个trait,定义了执行策略的接口。
MessagePipe<T>
是一个trait,定义了消息的接口,包括发送和接收消息。
以上是关于该文件中结构体和trait的简要介绍,具体实现和用途需要结合源码进行深入理解。
File: rust/library/proc_macro/src/bridge/mod.rs
在Rust源代码中,rust/library/proc_macro/src/bridge/mod.rs文件的作用是实现了用于与编译器进行交互的过程宏桥接的相关功能。
该文件中定义了一些结构体和枚举,这些结构体和枚举被用于描述和表示Rust编译器和过程宏之间的通信和数据交换。
-
BridgeConfig<'a>结构体用于表示桥接配置,其中的字段和选项可用于配置过程宏的行为和特性。 -
Marked 结构体用于表示带有标记的值,用于标记并追踪编译器的处理过程中的某个特定值。 -
DelimSpan 结构体用于表示带有定界符的源代码范围,用于跟踪源代码中的定界符。 -
Group 结构体用于表示一个词法分组,即一组TokenStream。 -
Punct 结构体用于表示标点符号,包括标点符号的内容和源代码中的位置信息。 -
Ident 结构体用于表示标识符,包括标识符的内容和源代码中的位置信息。 -
Literal 结构体用于表示字面量,包括字面量的内容和源代码中的位置信息。 -
Diagnostic 结构体用于表示编译器的诊断信息,包括错误、警告等信息,并包含位置信息。 -
ExpnGlobals 结构体用于表示扩展全局变量,用于保存编译器扩展过程中的一些全局状态信息。 -
Range 结构体用于表示一个范围,可用于表示代码中的一个区间。
Mark和Unmark trait分别用于在编译器处理过程中对值进行标记和取消标记操作,用于记录和跟踪某个特定值的处理过程。
$name枚举用于表示名称,存储一个标识符的名称。
Method枚举用于表示方法,存储一个过程宏的方法。
Delimiter枚举用于表示定界符,包括大括号、方括号、圆括号等。
Level枚举用于表示级别,用于表示编译器处理过程中的不同级别。
Spacing枚举用于表示间距,用于表示编译器处理过程中不同操作之间的间距。
LitKind枚举用于表示字面量的种类,包括整数、浮点数、字符串等。
Bound 枚举用于表示边界,表示一个泛型参数的约束条件。
Option 枚举用于表示一个可选值,表示某个值可能存在或不存在。
Result 枚举用于表示结果,表示一个操作可能产生的成功或失败结果。
TokenTree 枚举用于表示一个TokenStream的语法树节点。
File: rust/library/proc_macro/src/lib.rs
在Rust的源代码中,rust/library/proc_macro/src/lib.rs文件的作用是实现了proc_macro
库,该库是Rust语言用于编写编译器插件和自定义的过程宏的核心库。下面对该文件中的一些重要结构进行详细介绍。
-
TokenStream(Optionbridge::client::TokenStream): 这是一个结构体,代表了一个由语法层面的标记(tokens)组成的流。
TokenStream
可以通过parse
方法将字符串转换为标记流,也可以通过into() -> TokenStream
将一个标记流转换为另一个标记流。 -
LexError: 这是一个枚举值,表示在解析过程中可能出现的词法错误,例如未知的字符或不正确的标记序列。
-
ExpandError: 这是一个枚举值,表示在将过程宏扩展应用于标记流时可能出现的错误,例如无法解析的模式或类型错误。
-
ConcatTreesHelper, ConcatStreamsHelper: 这两个结构体分别用于处理
TokenTree
和TokenStream
的连接操作。 -
IntoIter(Span(bridge::client::Span);,SourceFile(bridge::client::SourceFile);,Group(bridge::Group<bridge::client::TokenStream,,Punct(bridge::Punctbridge::client::Span);,Ident(bridge::Ident<bridge::client::Span,,Literal(bridge::Literal<bridge::client::Span:
IntoIter
是TokenStream
的迭代器,迭代产生不同类型的标记子树。Span
代表一个标记的位置信息,SourceFile
代表一个源文件的信息,Group
代表一个标记组,Punct
代表一个标点符号标记,Ident
代表一个标识符标记,Literal
代表一个字面量标记。
以上是几个结构体的作用说明,接下来解释几个枚举类型的作用:
-
TokenTree: 它是
TokenStream
中的一个元素,可以是Group
、Punct
、Ident
或Literal
中的任意一种。用于表示标记流中的单个标记树。 -
Delimiter: 它是
Group
结构体中的一个成员,用于表示标记组的分隔符类型,可以是花括号、方括号或圆括号。 -
Spacing: 它是在
Group
、Ident
和Punct
结构体中使用的枚举类型,用于表示与之前标记之间的空白间隔类型,可以是一个或多个空格、换行符或其他。
通过以上的介绍,你应该能够了解到rust/library/proc_macro/src/lib.rs文件实现的proc_macro
库提供了一系列用于操作、解析和生成标记流的数据结构和方法。在Rust的编译器插件和过程宏中,这些工具是非常有用的。
File: rust/library/proc_macro/src/diagnostic.rs
在Rust源代码中,rust/library/proc_macro/src/diagnostic.rs文件的作用是实现了用于处理编译器诊断信息的结构体和相关功能。
该文件定义了许多与诊断相关的结构体和枚举类型,其中最重要的是Diagnostic结构体。此结构体表示了一个编译器诊断信息,它包含了该诊断的级别(Level)和消息内容(Message),以及诊断所在的源代码位置(Span)等,还包含其他的辅助信息。通过Diagnostic结构体,可以收集和呈现编译器诊断信息。
另外,还有一个重要的结构体Children<'a>(std::slice::Iter<'a, Diagnostic>),它表示了一组Diagnostic的子集合。通过Children结构体,可以将多个相关的Diagnostic信息分组展示,可用于表示诊断链。
接下来,让我们详细介绍一下这些结构体和枚举类型的作用:
-
Diagnostic结构体:代表一个编译器诊断信息。它包含了以下字段:
-
level(Level枚举类型):表示诊断的级别,如错误、警告等。 -
message(Message结构体):表示诊断的消息内容,包括错误信息、建议等。 -
spans(Vec ):表示诊断所在的源代码位置,支持多个Span。 -
children(Option<Children<'a>>):表示与该诊断相关的子诊断链。
-
-
Children<'a>(std::slice::Iter<'a, Diagnostic>)结构体:代表Diagnostic的子集合。它实现了Iterator trait,可以用于遍历和处理多个相关的Diagnostic信息。通过将相关的Diagnostic信息放在Children结构体中,可以更好地组织和呈现诊断链。
-
MultiSpan trait:定义了处理多个Span的行为。它包含了以下方法:
-
spans(self) -> Vec :返回多个Span的集合。 -
primary_span(self) -> Span:返回主要的Span。
-
-
Level枚举类型:表示诊断的级别。它包含了以下值:
-
Error:代表错误级别的诊断。 -
Warning:代表警告级别的诊断。 -
Note:代表注解级别的诊断。 -
Help:代表帮助级别的诊断。
-
以上就是在Rust源代码中,rust/library/proc_macro/src/diagnostic.rs文件中常用结构体和枚举类型的作用介绍。它们提供了一种用于处理编译器诊断信息的工具,可以更好地收集、组织和呈现编译器的诊断结果。
File: rust/library/proc_macro/src/quote.rs
在Rust源代码中,quote.rs
文件位于proc_macro
库的路径下,其作用是提供了一个宏(quote!
)和相关的类型和函数,用于在编译时生成代码。以下是对其详细介绍:
quote.rs
文件是proc_macro
库的一部分,这是用于处理Rust语言中的宏的库。宏是一种在编译时生成重复代码的机制,使用宏允许开发人员在代码中根据需要生成其他代码。
quote.rs
定义了一个非常重要的宏,即quote!
宏。这个宏可以接受一系列的代码片段,并将它们组合成一个新的代码片段。它允许开发者使用Rust的语法树结构,以编程方式构建和生成代码。
quote!
宏背后的实现逻辑非常复杂,它使用了Rust的程序库proc_macro2
来处理和操作语法树。在内部,quote!
宏会将输入的代码片段解析为语法树节点,然后将这些节点组合到新的语法树中。最终,quote!
宏将生成的语法树逆向解析为可执行的代码。
通过使用quote!
宏,开发人员可以通过编写Rust代码来生成其他Rust代码。这在许多情况下都非常有用,特别是当需要在编译时动态生成代码以适应不同的需求时。该宏广泛应用于Rust生态系统中的各种库和框架,例如Rust的派生库(derive
attribute)、代码生成工具等。
总之,quote.rs
文件提供了一个强大的宏和相关的类型和函数,允许开发者在编译时以编程方式生成Rust代码。它通过解析、重组和逆向解析语法树实现了这一功能,为Rust生态系统中的宏和代码生成提供了重要的基础。文章来源:https://www.toymoban.com/news/detail-769987.html
本文由 mdnice 多平台发布文章来源地址https://www.toymoban.com/news/detail-769987.html
到了这里,关于听GPT 讲Rust源代码--library/proc_macro的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!